summaryrefslogtreecommitdiff
path: root/web/glasgow
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/glasgow
Initial commit
Diffstat (limited to 'web/glasgow')
-rw-r--r--web/glasgow/lit2x-0.16/README16
-rw-r--r--web/glasgow/lit2x-0.16/STARTUP-literate58
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/Jmakefile6
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT58
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL1
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/README48
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile5
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/etags/README2
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c1757
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes568
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes545
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile7
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c520
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms128
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile18
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout11
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/msub/testfile11
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes180
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile79
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl126
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh2
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c217
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man61
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh85
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl215
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl502
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl186
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man15
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh24
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh26
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl49
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl69
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl184
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/scripts/zap-if-same.prl50
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/verbatim/Jmakefile4
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.c533
-rw-r--r--web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.lex57
-rw-r--r--web/glasgow/lit2x-0.16/literate/Jmakefile131
-rw-r--r--web/glasgow/lit2x-0.16/literate/MAIL.ireland76
-rw-r--r--web/glasgow/lit2x-0.16/literate/Makefile.BOOT58
-rw-r--r--web/glasgow/lit2x-0.16/literate/PATCHLEVEL1
-rw-r--r--web/glasgow/lit2x-0.16/literate/PROJECTS64
-rw-r--r--web/glasgow/lit2x-0.16/literate/README38
-rw-r--r--web/glasgow/lit2x-0.16/literate/TeX-Mathematica-note34
-rw-r--r--web/glasgow/lit2x-0.16/literate/a-cpp-ish-thing-from-the-net257
-rw-r--r--web/glasgow/lit2x-0.16/literate/code-bug.tex50
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/Jmakefile8
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/REM.comments239
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/april91.lit572
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/caveats.lit45
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/habits.lit34
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/highlights.lit354
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/install.lit96
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/lang_ref.lit472
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/lang_specific.lit50
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/lang_tut.lit658
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/lit_mode.lit3
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/literate.dvibin0 -> 145648 bytes
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/literate.info3390
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/literate.lit104
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/programs.lit300
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/sept92.lit45
-rw-r--r--web/glasgow/lit2x-0.16/literate/doc/using.lit6
-rw-r--r--web/glasgow/lit2x-0.16/literate/furuta_ref28
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/ChangeLog495
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/Jmakefile52
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/Makefile.in124
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/Makefile.original69
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/README15
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/bug.texi12
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/configure429
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/configure.in15
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/default-nodes.texinfo40
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/getopt.c681
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/getopt.h121
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/getopt1.c158
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/info.1101
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/info.c4744
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/info.el1910
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/linebreaks.texi18
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.c7522
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.texinfo226
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/postmakeinfo.prl81
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/test-suite.texinfo167
-rw-r--r--web/glasgow/lit2x-0.16/literate/info-utils/testfile.texinfo130
-rw-r--r--web/glasgow/lit2x-0.16/literate/leathrum_on_pgm_typesetting.tex59
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2changes.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2depend.lprl56
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-c.lprl122
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-f.lprl154
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-hs.lprl304
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-jm.lprl64
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-lex.lprl27
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-none.lprl21
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc-prl.lprl111
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2doc.lprl369
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-c.lprl22
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-f.lprl22
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-hs.lprl22
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-jm.lprl22
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-lex.lprl23
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-none.lprl23
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex-prl.lprl22
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2latex.lprl329
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-c.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-f.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-hs.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-jm.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-lex.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-none.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm-prl.lprl12
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2pgm.lprl53
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-c.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-f.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-hs.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-jm.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-lex.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-none.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi-prl.lprl6
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2texi.lprl434
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-2text.lprl23
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-deatify.c2084
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-deatify.lex538
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-deatify.llex669
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-globals.lprl381
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-inputter.lprl121
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-inputter.prl104
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-link-globals.lprl9
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-linker.lprl525
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-reader.lprl588
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit-style.tex1152
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit2pgm.BOOT385
-rw-r--r--web/glasgow/lit2x-0.16/literate/lit2stuff.lprl775
-rw-r--r--web/glasgow/lit2x-0.16/literate/typesetting-code1061
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/Jmakefile72
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/Makefile.BOOT80
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/Makefile.DUMMY21
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/PATCHLEVEL1
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/README26
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/TEMPLATE.jm199
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/TEMPLATE.ljm322
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/ccjmake.c21
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/Jmakefile9
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/appendix-X11R4.ms2413
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/config-X11R4-1.05.ms2456
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/config-wrprc.ms691
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/imake-moraes.tex884
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/Jmakefile4
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/mkw_guide.lit716
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/Jmakefile6
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/mkw_ref.lit72
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/install-GEN.jm139
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/install-GEN.ljm145
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/jmake.c922
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/jmakemdep.h379
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/jmkmf.prl130
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/jrestoredeps63
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/macros-GEN.jm853
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/macros-GEN.ljm1180
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-DEF.jm27
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-DEF.ljm38
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.jm50
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.ljm290
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-alpha.jm20
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-alpha.ljm27
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-linux.jm26
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-linux.ljm36
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.jm51
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.ljm100
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-sun.jm32
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/plat-sun.ljm39
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/site-DEF.jm45
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/site-DEF.ljm53
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/site.dist147
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.jm154
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.ljm290
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/utils-GEN.jm1096
-rw-r--r--web/glasgow/lit2x-0.16/mkworld/utils-GEN.ljm1130
178 files changed, 56907 insertions, 0 deletions
diff --git a/web/glasgow/lit2x-0.16/README b/web/glasgow/lit2x-0.16/README
new file mode 100644
index 0000000000..76d5b0ad20
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/README
@@ -0,0 +1,16 @@
+This is the root directory for software distributed by the AQUA
+project in the Computing Science Dept at Glasgow University. At
+present, we have three different distributions, which share some
+components.
+
+ ghc the Glasgow Haskell compilation system
+ nofib the NoFib Haskell benchmarking suite
+ literate the Glasgow "literate programming" system
+
+The "literate" stuff is usually distributed *with* other systems, but
+not necessarily. Components which are always part of a distribution
+(never stand-alone) are "grasp-utils" and "mkworld" (a configuration
+system).
+
+Please consult the {ghc,nofib,literate}/README file to find out how to
+proceed.
diff --git a/web/glasgow/lit2x-0.16/STARTUP-literate b/web/glasgow/lit2x-0.16/STARTUP-literate
new file mode 100644
index 0000000000..63e11e32e6
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/STARTUP-literate
@@ -0,0 +1,58 @@
+#! /bin/sh
+#
+# die quickly if anything goes astray...
+set -e
+
+echo '*******************************************************************'
+echo '* I hope that you read the relevant documentation and tweaked the *'
+echo '* appropriate configuration files _BEFORE_ you started running *'
+echo '* this! *'
+echo '*******************************************************************'
+
+echo ''
+echo "*** We don't project-ify or setup-ify this distribution..."
+echo ''
+PROJECT=none
+SETUP=std
+
+# figure out the absolute pathname of the "top" directory
+# (the one which has "mkworld", "nofib", "grasp-utils", etc., as subdirs)
+hardtop=`pwd`
+hardtop=`echo $hardtop | sed 's|^/tmp_mnt||' | sed 's|^/export||' | sed 's|^/grasp_tmp|/local/grasp_tmp|'`
+echo ''
+echo "*** I decided the top of your build tree is: $hardtop"
+
+# make all the Makefiles first
+
+for i in mkworld grasp-utils literate ; do
+ ( set -e; \
+ cd $i ; \
+ echo '' ; \
+ echo "*** configuring $i ..." ; \
+ make -f Makefile.BOOT BOOT_DEFINES="-P none -S std -DTopDirPwd=$hardtop"; \
+ echo '' ; \
+ echo "*** making Makefiles in $i ..." ; \
+ make Makefiles \
+ )
+done
+
+# now make the dependencies and Real Stuff
+
+for i in mkworld literate grasp-utils ; do
+ ( set -e; \
+ cd $i ; \
+ echo '' ; \
+ echo "*** making make dependencies in $i ..." ; \
+ make depend ; \
+ echo '' ; \
+ echo "*** making all in $i ..." ; \
+ make all \
+ )
+done
+
+echo ''
+echo '*******************************************************************'
+echo "* You should be ready to install, test, etc., this system..."
+echo "* (Please consult the documentation.)"
+echo '*******************************************************************'
+exit 0
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile
new file mode 100644
index 0000000000..96625e3d52
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile
@@ -0,0 +1,6 @@
+#define IHaveSubdirs
+
+SUBDIRS = scripts \
+ msub \
+ etags \
+ verbatim
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT b/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT
new file mode 100644
index 0000000000..16179c7df1
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT
@@ -0,0 +1,58 @@
+# hand-hacked Makefile to boot the "make world" process
+#---------------------------------------------------------------------
+
+# Platform-specific configuration stuff was read from: sun.cf
+
+SHELL = /bin/sh
+PATHSEP = /
+
+TOP = ..
+CURRENT_DIR = ./grasp-utils
+
+RM=rm -f
+MV=mv -f
+BOOTSTRAPCFLAGS =
+
+# Project identification -- name, version, and stuff
+
+PROJECTNAME = Booting the Make World System
+PROJECTVERSION = none
+PROJECTLABEL = none
+SETUPLABEL = std
+
+PROJECTCONFIGDIR =
+
+###########################################################################
+# Configuration stuff (jmake, its friends and templates)
+
+JMKMF = jmkmf_used_only_with_installed_utils
+JRESTOREDEPS = $(JMAKESRC)/jrestoredeps
+JMAKE = $(JMAKESRC)/jmake
+JMAKE_DEFINES =
+
+JMAKESRC = $(TOP)/mkworld
+
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) $(BOOT_DEFINES)
+
+###########################################################################
+
+Makefile:: $(JMAKE)
+
+$(JMAKE):
+ @(cd $(JMAKESRC); if [ -f Makefile ]; then \
+ echo "checking $@ in $(JMAKESRC) first..."; $(MAKE) all; else \
+ echo "bootstrapping $@ from Makefile.BOOT in $(JMAKESRC) first..."; \
+ $(MAKE) -f Makefile.BOOT BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \
+ echo "okay, continuing in $(CURRENT_DIR)")
+
+Makefile::
+ -@if [ -f Makefile ]; then \
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(JMAKE_CMD)
+ $(JRESTOREDEPS)
+ @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi
+ @chmod 444 Makefile
+ @echo ==== The new Makefile is for\: ====
+ @$(MAKE) whoami
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL b/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL
new file mode 100644
index 0000000000..9667fc05ed
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL
@@ -0,0 +1 @@
+Miscellaneous GRASP-project tools, version 0.16, patchlevel 0
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/README b/web/glasgow/lit2x-0.16/grasp-utils/README
new file mode 100644
index 0000000000..a98feebe81
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/README
@@ -0,0 +1,48 @@
+This directory tree's worth of stuff are utility bits that are used in
+more than one of our GRASP projects. (For the project-specific bits,
+try <project>/utils/<blah>.)
+
+msub/ a utility from Paul DuBois, that lets you substitute
+ for make variables (e.g., $(CC) ) in any old document.
+ Given that, with the "make world" configuration
+ system, Makefiles have loads of useful config info in
+ them, this is the program used to sneak that info into
+ other files.
+
+ugen/ A utility from the LML-compiler distrib to support
+ poor man's abstract data types for C. Used in the
+ parser ($(TOP)/parsers/hsp).
+
+scripts/ little utility scripts
+
+ lndir from X imake stuff (via DuBois); make a shadow tree
+ of symbolic links
+ mkdirhier "mkdir a/b/c/d" will do "mkdir a; mkdir a/b; ..."
+ (assuming none of those dirs exist)
+
+ runstdtest runs a pgm with some flags & some stdin; checks for an
+ expected exit code, expected stdout, and expected
+ stderr. (Expect this to change :-)
+
+ newer "newer a b" (obsolete?) exit code 0 if file "a" newer
+ than "b", or something like that...
+
+ tidycpp, hscpp cpp (C pre-processor) wrappers, the latter for
+ Haskell, the former obsolete?
+
+ mkdependC script version of C makedepend (from X11R4 via DuBois)
+ mkdependHS "make depend" (perl) script for Haskell code.
+
+ mkdependLML simon's makedepend1 script (needs work to function here)
+ (NOT BUILT)
+
+ fastmake a "make" wrapper for compiling Haskell programs;
+ essentially, strips out the "make depend"ed
+ dependencies to avoid so much re-checking.
+
+ update_iface a REALLY HORRIBLE hack, for updating the new Haskell
+ compiler's interface files; covers for deficiencies in
+ "nhc" (prototype compiler) i/face handling.
+
+ ltx a "latex" wrapper. Re-runs latex/bibtex/makeindex
+ enough times to "do the right thing."
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile
new file mode 100644
index 0000000000..cadc4636d6
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile
@@ -0,0 +1,5 @@
+BuildPgmFromOneCFile(etags)
+
+InstallBinaryTarget(etags,$(INSTBINDIR))
+
+CDependTarget( $(SRCS_C) )
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/README b/web/glasgow/lit2x-0.16/grasp-utils/etags/README
new file mode 100644
index 0000000000..fb033eabe1
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/README
@@ -0,0 +1,2 @@
+This is the "etags" program from the GNU emacs (18.??) distribution.
+Kevin Hammond has hacked it slightly to recognise more kinds of files.
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c b/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c
new file mode 100644
index 0000000000..5abb1990a1
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c
@@ -0,0 +1,1757 @@
+/* Tags file maker to go with GNUmacs
+ Copyright (C) 1984, 1987, 1988 Free Software Foundation, Inc. and Ken Arnold
+
+ NO WARRANTY
+
+ BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
+WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
+OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
+A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
+PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
+
+ GENERAL PUBLIC LICENSE TO COPY
+
+ 1. You may copy and distribute verbatim copies of this source file
+as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy a valid copyright notice
+"Copyright (C) 1986 Free Software Foundation"; and include
+following the copyright notice a verbatim copy of the above disclaimer
+of warranty and of this License.
+
+ 2. You may modify your copy or copies of this source file or
+any portion of it, and copy and distribute such modifications under
+the terms of Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of this
+ program or any part thereof, to be licensed at no charge to all
+ third parties on terms identical to those contained in this
+ License Agreement (except that you may choose to grant more extensive
+ warranty protection to some or all third parties, at your option).
+
+ c) You may charge a distribution fee for the physical act of
+ transferring a copy, and you may at your option offer warranty
+ protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+ 3. You may copy and distribute this program (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the terms
+of Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal
+ shipping charge) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+ 4. You may not copy, sublicense, distribute or transfer this program
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer this program is void and
+your rights to use the program under this License agreement shall be
+automatically terminated. However, parties who have received computer
+software programs from you with this License Agreement will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+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! */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* Define the symbol ETAGS to make the program "etags",
+ which makes emacs-style tag tables by default.
+ Define CTAGS to make the program "ctags" compatible with the usual one.
+ Define neither one to get behavior that depends
+ on the name with which the program is invoked
+ (but we don't normally compile it that way). */
+
+/* On VMS, CTAGS is not useful, so always do ETAGS. */
+#ifdef VMS
+#ifndef ETAGS
+#define ETAGS
+#endif
+#endif
+
+/* Exit codes for success and failure. */
+
+#ifdef VMS
+#define GOOD (1)
+#define BAD (0)
+#else
+#define GOOD (0)
+#define BAD (1)
+#endif
+
+#define reg register
+#define logical char
+
+#define TRUE (1)
+#define FALSE (0)
+
+#define iswhite(arg) (_wht[arg]) /* T if char is white */
+#define begtoken(arg) (_btk[arg]) /* T if char can start token */
+#define intoken(arg) (_itk[arg]) /* T if char can be in token */
+#define endtoken(arg) (_etk[arg]) /* T if char ends tokens */
+#define isgood(arg) (_gd[arg]) /* T if char can be after ')' */
+
+#define max(I1,I2) (I1 > I2 ? I1 : I2)
+
+/* cause token checking for typedef, struct, union, enum to distinguish
+ keywords from identifier-prefixes (e.g. struct vs struct_tag). */
+#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
+
+struct nd_st { /* sorting structure */
+ char *name; /* function or type name */
+ char *file; /* file name */
+ logical f; /* use pattern or line no */
+ int lno; /* line number tag is on */
+ long cno; /* character number line starts on */
+ char *pat; /* search pattern */
+ logical been_warned; /* set if noticed dup */
+ struct nd_st *left,*right; /* left and right sons */
+};
+
+long ftell();
+typedef struct nd_st NODE;
+
+int number; /* tokens found so far on line starting with # (including #) */
+logical gotone, /* found a func already on line */
+ /* boolean "func" (see init) */
+ _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
+
+ /* typedefs are recognized using a simple finite automata,
+ * tydef is its state variable.
+ */
+typedef enum {none, begin, tag_ok, middle, end } TYST;
+
+TYST tydef = none;
+
+char searchar = '/'; /* use /.../ searches */
+
+int lineno; /* line number of current line */
+long charno; /* current character number */
+long linecharno; /* character number of start of line */
+
+char *curfile, /* current input file name */
+ *outfile= 0, /* output file */
+ *white = " \f\t\n", /* white chars */
+ *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?",
+ /* token ending chars */
+ *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$",
+ /* token starting chars */
+ *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789",
+ /* valid in-token chars */
+ *notgd = ",;"; /* non-valid after-function chars */
+
+int file_num = 0; /* current file number */
+int aflag = 0; /* -a: append to tags */
+int tflag = 0; /* -t: create tags for typedefs */
+int uflag = 0; /* -u: update tags */
+int wflag = 0; /* -w: suppress warnings */
+int vflag = 0; /* -v: create vgrind style index output */
+int xflag = 0; /* -x: create cxref style output */
+int eflag = 0; /* -e: emacs style output */
+
+/* Name this program was invoked with. */
+char *progname;
+
+FILE *inf, /* ioptr for current input file */
+ *outf; /* ioptr for tags file */
+
+NODE *head; /* the head of the sorted binary tree */
+
+char *savestr();
+char *savenstr ();
+char *rindex();
+char *index();
+char *concat ();
+void initbuffer ();
+long readline ();
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+ `readline' reads a line from a stream into a linebuffer
+ and works regardless of the length of the line. */
+
+struct linebuffer
+ {
+ long size;
+ char *buffer;
+ };
+
+struct linebuffer lb, lb1;
+
+#if 0 /* VMS now provides the `system' function. */
+#ifdef VMS
+
+#include <descrip.h>
+
+void
+system (buf)
+ char *buf;
+{
+ struct dsc$descriptor_s command =
+ {
+ strlen(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf
+ };
+
+ LIB$SPAWN(&command);
+}
+#endif /* VMS */
+#endif /* 0 */
+
+main(ac,av)
+ int ac;
+ char *av[];
+{
+ char cmd[100];
+ int i;
+ int fflag = 0;
+ char *this_file;
+#ifdef VMS
+ char got_err;
+
+ extern char *gfnames();
+ extern char *massage_name();
+#endif
+
+ progname = av[0];
+
+#ifdef ETAGS
+ eflag = 1;
+#else
+#ifdef CTAGS
+ eflag = 0;
+#else
+ {
+ char *subname = rindex (progname, '/');
+ if (subname++ == NULL)
+ subname = progname;
+ eflag = ! strcmp(subname, "ctags");
+ }
+#endif
+#endif
+
+ while (ac > 1 && av[1][0] == '-')
+ {
+ for (i=1; av[1][i]; i++)
+ {
+ switch(av[1][i])
+ {
+#ifndef VMS /* These options are useful only with ctags,
+ and VMS can't input them, so just omit them. */
+ case 'B':
+ searchar='?';
+ eflag = 0;
+ break;
+ case 'F':
+ searchar='/';
+ eflag = 0;
+ break;
+#endif
+ case 'a':
+ aflag++;
+ break;
+ case 'e':
+ eflag++;
+ break;
+ case 'f':
+ if (fflag > 0)
+ {
+ fprintf(stderr,
+ "%s: -f flag may only be given once\n", progname);
+ goto usage;
+ }
+ fflag++, ac--; av++;
+ if (ac <= 1 || av[1][0] == '\0')
+ {
+ fprintf(stderr,
+ "%s: -f flag must be followed by a filename\n",
+ progname);
+ goto usage;
+ }
+ outfile = av[1];
+ goto end_loop;
+ case 't':
+ tflag++;
+ break;
+#ifndef VMS
+ case 'u':
+ uflag++;
+ eflag = 0;
+ break;
+#endif
+ case 'w':
+ wflag++;
+ break;
+ case 'v':
+ vflag++;
+ xflag++;
+ eflag = 0;
+ break;
+ case 'x':
+ xflag++;
+ eflag = 0;
+ break;
+ default:
+ goto usage;
+ }
+ }
+ end_loop: ;
+ ac--; av++;
+ }
+
+ if (ac <= 1)
+ {
+ usage:
+#ifdef VMS
+ fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
+#else
+ fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname);
+#endif
+ exit(BAD);
+ }
+
+ if (outfile == 0)
+ {
+ outfile = eflag ? "TAGS" : "tags";
+ }
+
+ init(); /* set up boolean "functions" */
+
+ initbuffer (&lb);
+ initbuffer (&lb1);
+ /*
+ * loop through files finding functions
+ */
+ if (eflag)
+ {
+ outf = fopen (outfile, aflag ? "a" : "w");
+ if (!outf)
+ {
+ fprintf (stderr, "%s: ", progname);
+ perror (outfile);
+ exit (BAD);
+ }
+ }
+
+ file_num = 1;
+#ifdef VMS
+ for (ac--, av++;
+ (this_file = gfnames (&ac, &av, &got_err)) != NULL; file_num++)
+ {
+ if (got_err)
+ {
+ error("Can't find file %s\n", this_file);
+ ac--, av++;
+ }
+ else
+ {
+ this_file = massage_name (this_file);
+#else
+ for (; file_num < ac; file_num++)
+ {
+ this_file = av[file_num];
+ if (1)
+ {
+#endif
+ find_entries (this_file);
+ if (eflag)
+ {
+ fprintf (outf, "\f\n%s,%d\n",
+ this_file, total_size_of_entries (head));
+ put_entries (head);
+ free_tree (head);
+ head = NULL;
+ }
+ }
+ }
+
+ if (eflag)
+ {
+ fclose (outf);
+ exit (GOOD);
+ }
+
+ if (xflag)
+ {
+ put_entries(head);
+ exit(GOOD);
+ }
+ if (uflag)
+ {
+ for (i=1; i<ac; i++)
+ {
+ sprintf(cmd,
+ "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
+ outfile, av[i], outfile);
+ system(cmd);
+ }
+ aflag++;
+ }
+ outf = fopen(outfile, aflag ? "a" : "w");
+ if (outf == NULL)
+ {
+ fprintf (stderr, "%s: ", outfile);
+ perror(outfile);
+ exit(BAD);
+ }
+ put_entries(head);
+ fclose(outf);
+#ifndef VMS
+ if (uflag)
+ {
+ sprintf(cmd, "sort %s -o %s", outfile, outfile);
+ system(cmd);
+ }
+#endif
+ exit(GOOD);
+}
+
+/*
+ * This routine sets up the boolean psuedo-functions which work
+ * by seting boolean flags dependent upon the corresponding character
+ * Every char which is NOT in that string is not a white char. Therefore,
+ * all of the array "_wht" is set to FALSE, and then the elements
+ * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
+ * of a char is TRUE if it is the string "white", else FALSE.
+ */
+init()
+{
+
+ reg char *sp;
+ reg int i;
+
+ for (i = 0; i < 0177; i++)
+ {
+ _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
+ _gd[i] = TRUE;
+ }
+ for (sp = white; *sp; sp++)
+ _wht[*sp] = TRUE;
+ for (sp = endtk; *sp; sp++)
+ _etk[*sp] = TRUE;
+ for (sp = intk; *sp; sp++)
+ _itk[*sp] = TRUE;
+ for (sp = begtk; *sp; sp++)
+ _btk[*sp] = TRUE;
+ for (sp = notgd; *sp; sp++)
+ _gd[*sp] = FALSE;
+ _wht[0] = _wht['\n'];
+ _etk[0] = _etk['\n'];
+ _btk[0] = _btk['\n'];
+ _itk[0] = _itk['\n'];
+ _gd[0] = _gd['\n'];
+}
+
+/*
+ * This routine opens the specified file and calls the function
+ * which finds the function and type definitions.
+ */
+find_entries (file)
+ char *file;
+{
+ char *cp;
+
+ if ((inf=fopen(file,"r")) == NULL)
+ {
+ fprintf (stderr, "%s: ", progname);
+ perror(file);
+ return;
+ }
+ curfile = savestr(file);
+ cp = rindex(file, '.');
+ /* .tex, .aux or .bbl implies LaTeX source code */
+ if (cp && (!strcmp (cp + 1, "tex") || !strcmp (cp + 1, "aux")
+ || !strcmp (cp + 1, "bbl")))
+ {
+ TEX_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
+ if (cp && (!strcmp (cp + 1, "l") ||
+ !strcmp (cp + 1, "el") ||
+ !strcmp (cp + 1, "lsp") ||
+ !strcmp (cp + 1, "lisp") ||
+ !strcmp (cp + 1, "cl") ||
+ !strcmp (cp + 1, "clisp")))
+ {
+ L_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* .scm or .sm or .scheme implies scheme source code */
+ if (cp && (!strcmp (cp + 1, "sm")
+ || !strcmp (cp + 1, "scm")
+ || !strcmp (cp + 1, "scheme")
+ || !strcmp (cp + 1, "t")
+ || !strcmp (cp + 1, "sch")
+ || !strcmp (cp + 1, "SM")
+ || !strcmp (cp + 1, "SCM")
+ /* The `SCM' or `scm' prefix with a version number */
+ || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's')
+ || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S')))
+ {
+ Scheme_funcs(inf);
+ fclose(inf);
+ return;
+ }
+ /* .M implies Mcode source code */
+ if (cp && !strcmp (cp + 1, "M"))
+ {
+ Mcode_funcs(inf);
+ fclose(inf);
+ return;
+ }
+
+ /* if not a .c or .h or .y file, try fortran */
+ if (cp && (cp[1] != 'c' && cp[1] != 'h' && cp[1] != 'y')
+ && cp[2] == '\0')
+ {
+ if (PF_funcs(inf) != 0)
+ {
+ fclose(inf);
+ return;
+ }
+ rewind(inf); /* no fortran tags found, try C */
+ }
+ C_entries();
+ fclose(inf);
+}
+
+/* Record a tag on the current line.
+ name is the tag name,
+ f is nonzero to use a pattern, zero to use line number instead. */
+
+pfnote (name, f, linestart, linelen, lno, cno)
+ char *name;
+ logical f; /* f == TRUE when function */
+ char *linestart;
+ int linelen;
+ int lno;
+ long cno;
+{
+ register char *fp;
+ register NODE *np;
+ char *altname;
+ char tem[51];
+
+ if ((np = (NODE *) malloc (sizeof (NODE))) == NULL)
+ {
+ fprintf(stderr, "%s: too many entries to sort\n", progname);
+ put_entries(head);
+ free_tree(head);
+ head = NULL;
+ np = (NODE *) xmalloc(sizeof (NODE));
+ }
+ /* Change name "main" to M<thisfilename>. */
+ if (!eflag && !xflag && !strcmp(name, "main"))
+ {
+ fp = rindex(curfile, '/');
+ if (fp == 0)
+ fp = curfile;
+ else
+ fp++;
+ altname = concat ("M", fp, "");
+ fp = rindex(altname, '.');
+ if (fp && fp[2] == 0)
+ *fp = 0;
+ name = altname;
+ }
+ np->name = savestr(name);
+ np->file = curfile;
+ np->f = f;
+ np->lno = lno;
+ np->cno = cno;
+ np->left = np->right = 0;
+ if (eflag)
+ {
+ linestart[linelen] = 0;
+ }
+ else if (xflag == 0)
+ {
+ sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart);
+ linestart = tem;
+ }
+ np->pat = savestr (linestart);
+ if (head == NULL)
+ head = np;
+ else
+ add_node(np, head);
+}
+
+free_tree(node)
+ NODE *node;
+{
+ while (node)
+ {
+ free_tree(node->right);
+ free(node);
+ node = node->left;
+ }
+}
+
+add_node(node, cur_node)
+ NODE *node,*cur_node;
+{
+ register int dif;
+
+ dif = strcmp(node->name, cur_node->name);
+
+ /* If this tag name matches an existing one, then
+ unless -e was given, do not add the node, but maybe print a warning */
+ if (!eflag && !dif)
+ {
+ if (node->file == cur_node->file)
+ {
+ if (!wflag)
+ {
+ fprintf(stderr,"%s: Duplicate entry in file %s, line %d: %s\n",
+ progname, node->file,lineno,node->name);
+ fprintf(stderr,"Second entry ignored\n");
+ }
+ return;
+ }
+ if (!cur_node->been_warned)
+ if (!wflag)
+ fprintf(stderr,"%s: Duplicate entry in files %s and %s: %s (Warning only)\n",
+ progname, node->file, cur_node->file, node->name);
+ cur_node->been_warned = TRUE;
+ return;
+ }
+
+ /* Actually add the node */
+ if (dif < 0)
+ {
+ if (cur_node->left != NULL)
+ add_node(node,cur_node->left);
+ else
+ cur_node->left = node;
+ return;
+ }
+ if (cur_node->right != NULL)
+ add_node(node,cur_node->right);
+ else
+ cur_node->right = node;
+}
+
+put_entries(node)
+ reg NODE *node;
+{
+ reg char *sp;
+
+ if (node == NULL)
+ return;
+
+ /* Output subentries that precede this one */
+ put_entries (node->left);
+
+ /* Output this entry */
+
+ if (eflag)
+ {
+ fprintf (outf, "%s%c%d,%d\n",
+ node->pat, 0177, node->lno, node->cno);
+ }
+ else if (!xflag)
+ {
+ fprintf (outf, "%s\t%s\t",
+ node->name, node->file);
+
+ if (node->f)
+ { /* a function */
+ putc (searchar, outf);
+ putc ('^', outf);
+
+ for (sp = node->pat; *sp; sp++)
+ {
+ if (*sp == '\\' || *sp == searchar)
+ putc ('\\', outf);
+ putc (*sp, outf);
+ }
+ putc (searchar, outf);
+ }
+ else
+ { /* a typedef; text pattern inadequate */
+ fprintf (outf, "%d", node->lno);
+ }
+ putc ('\n', outf);
+ }
+ else if (vflag)
+ fprintf (stdout, "%s %s %d\n",
+ node->name, node->file, (node->lno+63)/64);
+ else
+ fprintf (stdout, "%-16s%4d %-16s %s\n",
+ node->name, node->lno, node->file, node->pat);
+
+ /* Output subentries that follow this one */
+ put_entries (node->right);
+}
+
+/* Return total number of characters that put_entries will output for
+ the nodes in the subtree of the specified node.
+ Works only if eflag is set, but called only in that case. */
+
+total_size_of_entries(node)
+ reg NODE *node;
+{
+ reg int total = 0;
+ reg long num;
+
+ if (node == NULL)
+ return 0;
+
+ /* Count subentries that precede this one */
+ total = total_size_of_entries (node->left);
+
+ /* Count subentries that follow this one */
+ total += total_size_of_entries (node->right);
+
+ /* Count this entry */
+
+ total += strlen (node->pat) + 3;
+
+ num = node->lno;
+ while (num)
+ {
+ total++;
+ num /= 10;
+ }
+
+ num = node->cno;
+ if (!num) total++;
+ while (num)
+ {
+ total++;
+ num /= 10;
+ }
+ return total;
+}
+
+/*
+ * This routine finds functions and typedefs in C syntax and adds them
+ * to the list.
+ */
+#ifdef VMS
+long vmslinecharno;
+#define VMS_SET_LINECHARNO (vmslinecharno = ftell(inf))
+#else
+#define VMS_SET_LINECHARNO
+#endif
+
+#define CNL_SAVE_NUMBER \
+{ \
+ VMS_SET_LINECHARNO; \
+ linecharno = charno; lineno++; \
+ charno += 1 + readline (&lb, inf); \
+ lp = lb.buffer; \
+}
+
+#define CNL \
+{ \
+ CNL_SAVE_NUMBER; \
+ number = 0; \
+}
+
+C_entries ()
+{
+ register int c;
+ register char *token, *tp, *lp;
+ logical incomm, inquote, inchar, midtoken;
+ int level;
+ char tok[BUFSIZ];
+
+ lineno = 0;
+ charno = 0;
+ lp = lb.buffer;
+ *lp = 0;
+
+ number = 0;
+ gotone = midtoken = inquote = inchar = incomm = FALSE;
+ level = 0;
+
+ while (!feof (inf))
+ {
+ c = *lp++;
+ if (c == 0)
+ {
+ CNL;
+ gotone = FALSE;
+ }
+ if (c == '\\')
+ {
+ c = *lp++;
+ if (c == 0)
+ CNL_SAVE_NUMBER;
+ c = ' ';
+ }
+ else if (incomm)
+ {
+ if (c == '*')
+ {
+ while ((c = *lp++) == '*')
+ continue;
+ if (c == 0)
+ CNL;
+ if (c == '/')
+ incomm = FALSE;
+ }
+ }
+ else if (inquote)
+ {
+ /*
+ * Too dumb to know about \" not being magic, but
+ * they usually occur in pairs anyway.
+ */
+ if (c == '"')
+ inquote = FALSE;
+ continue;
+ }
+ else if (inchar)
+ {
+ if (c == '\'')
+ inchar = FALSE;
+ continue;
+ }
+ else switch (c)
+ {
+ case '"':
+ inquote = TRUE;
+ continue;
+ case '\'':
+ inchar = TRUE;
+ continue;
+ case '/':
+ if (*lp == '*')
+ {
+ lp++;
+ incomm = TRUE;
+ }
+ continue;
+ case '#':
+ if (lp == lb.buffer + 1)
+ number = 1;
+ continue;
+ case '{':
+ if (tydef == tag_ok)
+ {
+ tydef=middle;
+ }
+ level++;
+ continue;
+ case '}':
+ if (lp == lb.buffer + 1)
+ level = 0; /* reset */
+ else
+ level--;
+ if (!level && tydef==middle)
+ {
+ tydef=end;
+ }
+ continue;
+ }
+ if (!level && !inquote && !incomm && gotone == FALSE)
+ {
+ if (midtoken)
+ {
+ if (endtoken(c))
+ {
+ int f;
+ char *buf = lb.buffer;
+ int endpos = lp - lb.buffer;
+ char *lp1 = lp;
+ int line = lineno;
+ long linestart = linecharno;
+#ifdef VMS
+ long vmslinestart = vmslinecharno;
+#endif
+ int tem = consider_token (&lp1, token, &f, level);
+ lp = lp1;
+ if (tem)
+ {
+ if (linestart != linecharno)
+ {
+#ifdef VMS
+ getline (vmslinestart);
+#else
+ getline (linestart);
+#endif
+ strncpy (tok, token + (lb1.buffer - buf),
+ tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb1.buffer, endpos, line, linestart);
+ }
+ else
+ {
+ strncpy (tok, token, tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb.buffer, endpos, line, linestart);
+ }
+ gotone = f; /* function */
+ }
+ midtoken = FALSE;
+ token = lp - 1;
+ }
+ else if (intoken(c))
+ tp++;
+ }
+ else if (begtoken(c))
+ {
+ token = tp = lp - 1;
+ midtoken = TRUE;
+ }
+ }
+ if (c == ';' && tydef==end) /* clean with typedefs */
+ tydef=none;
+ }
+}
+
+/*
+ * This routine checks to see if the current token is
+ * at the start of a function, or corresponds to a typedef
+ * It updates the input line * so that the '(' will be
+ * in it when it returns.
+ */
+consider_token (lpp, token, f, level)
+ char **lpp, *token;
+ int *f, level;
+{
+ reg char *lp = *lpp;
+ reg char c;
+ static logical next_token_is_func;
+ logical firsttok; /* T if have seen first token in ()'s */
+ int bad, win;
+
+ *f = 1; /* a function */
+ c = lp[-1];
+ bad = FALSE;
+ if (!number)
+ { /* space is not allowed in macro defs */
+ while (iswhite(c))
+ {
+ c = *lp++;
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ }
+ }
+ else
+ {
+ /* the following tries to make it so that a #define a b(c) */
+ /* doesn't count as a define of b. */
+
+ number++;
+ if (number >= 4 || (number==2 && strncmp (token, "define", 6)==0))
+ {
+ /* Force the next symbol to be recognised, even if it is #define a b(c)! */
+ if(number == 2) next_token_is_func = 1;
+ else
+ gotone = TRUE;
+ badone:
+ bad = TRUE;
+ goto ret;
+ }
+ }
+ /* check for the typedef cases */
+ if (tflag && istoken(token, "typedef", 7))
+ {
+ tydef=begin;
+ goto badone;
+ }
+ if (tydef==begin && (istoken(token, "struct", 6) ||
+ istoken(token, "union", 5) || istoken(token, "enum", 4)))
+ {
+ tydef=tag_ok;
+ goto badone;
+ }
+ if (tydef==tag_ok)
+ {
+ tydef=middle;
+ goto badone;
+ }
+ if (tydef==begin) /* e.g. typedef ->int<- */
+ {
+ tydef=end;
+ goto badone;
+ }
+ if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
+ {
+ tydef=end;
+ }
+ if (tydef==end)
+ {
+ *f = 0;
+ win = 1;
+ goto ret;
+ }
+ /* Detect GNUmacs's function-defining macros. */
+ if (!number && !strncmp (token, "DEF", 3))
+
+ {
+ next_token_is_func = 1;
+ goto badone;
+ }
+ if (next_token_is_func)
+ {
+ next_token_is_func = 0;
+ win = 1;
+ goto ret;
+ }
+ if (c != '(')
+ goto badone;
+ firsttok = FALSE;
+ while ((c = *lp++) != ')')
+ {
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ /*
+ * This line used to confuse ctags:
+ * int (*oldhup)();
+ * This fixes it. A nonwhite char before the first
+ * token, other than a / (in case of a comment in there)
+ * makes this not a declaration.
+ */
+ if (begtoken(c) || c=='/') firsttok++;
+ else if (!iswhite(c) && !firsttok) goto badone;
+ }
+ while (iswhite (c = *lp++))
+ {
+ if (c == 0)
+ {
+ if (feof (inf))
+ break;
+ CNL;
+ }
+ }
+ win = isgood (c);
+ret:
+ *lpp = lp - 1;
+ return !bad && win;
+}
+
+getline (atchar)
+ long atchar;
+{
+ long saveftell = ftell (inf);
+
+ fseek (inf, atchar, 0);
+ readline (&lb1, inf);
+ fseek (inf, saveftell, 0);
+}
+
+/* Fortran parsing */
+
+char *dbp;
+int pfcnt;
+
+PF_funcs(fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (*dbp == '%') dbp++ ; /* Ratfor escape to fortran */
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ switch (*dbp |' ')
+ {
+ case 'i':
+ if (tail("integer"))
+ takeprec();
+ break;
+ case 'r':
+ if (tail("real"))
+ takeprec();
+ break;
+ case 'l':
+ if (tail("logical"))
+ takeprec();
+ break;
+ case 'c':
+ if (tail("complex") || tail("character"))
+ takeprec();
+ break;
+ case 'd':
+ if (tail("double"))
+ {
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ if (tail("precision"))
+ break;
+ continue;
+ }
+ break;
+ }
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0)
+ continue;
+ switch (*dbp|' ')
+ {
+ case 'f':
+ if (tail("function"))
+ getit();
+ continue;
+ case 's':
+ if (tail("subroutine"))
+ getit();
+ continue;
+ case 'p':
+ if (tail("program"))
+ {
+ getit();
+ continue;
+ }
+ if (tail("procedure"))
+ getit();
+ continue;
+ }
+ }
+ return (pfcnt);
+}
+
+tail(cp)
+ char *cp;
+{
+ register int len = 0;
+
+ while (*cp && (*cp&~' ') == ((*(dbp+len))&~' '))
+ cp++, len++;
+ if (*cp == 0)
+ {
+ dbp += len;
+ return (1);
+ }
+ return (0);
+}
+
+takeprec()
+{
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp != '*')
+ return;
+ dbp++;
+ while (isspace(*dbp))
+ dbp++;
+ if (!isdigit(*dbp))
+ {
+ --dbp; /* force failure */
+ return;
+ }
+ do
+ dbp++;
+ while (isdigit(*dbp));
+}
+
+getit()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ while (isspace(*dbp))
+ dbp++;
+ if (*dbp == 0 || !isalpha(*dbp))
+ return;
+ for (cp = dbp+1; *cp && (isalpha(*cp) || isdigit(*cp)); cp++)
+ continue;
+ c = cp[0];
+ cp[0] = 0;
+ strcpy(nambuf, dbp);
+ cp[0] = c;
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+
+L_funcs (fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'D' || dbp[1] == 'd') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'F' || dbp[3] == 'f'))
+ {
+ while (!isspace(*dbp)) dbp++;
+ while (isspace(*dbp)) dbp++;
+ L_getit();
+ }
+ }
+}
+
+L_getit()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ if (*dbp == 0) return;
+ for (cp = dbp+1; *cp && *cp != '(' && *cp != ' '; cp++)
+ continue;
+ c = cp[0];
+ cp[0] = 0;
+ strcpy(nambuf, dbp);
+ cp[0] = c;
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+
+/*
+ * Scheme tag functions
+ * look for (def... xyzzy
+ * look for (def... (xyzzy
+ * look for (def ... ((...(xyzzy ....
+ * look for (set! xyzzy
+ */
+
+static get_scheme ();
+Scheme_funcs (fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'D' || dbp[1] == 'd') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'F' || dbp[3] == 'f'))
+ {
+ while (!isspace(*dbp)) dbp++;
+ /* Skip over open parens and white space */
+ while (*dbp && (isspace(*dbp) || *dbp == '(')) dbp++;
+ get_scheme ();
+ }
+ if (dbp[0] == '(' &&
+ (dbp[1] == 'S' || dbp[1] == 's') &&
+ (dbp[2] == 'E' || dbp[2] == 'e') &&
+ (dbp[3] == 'T' || dbp[3] == 't') &&
+ (dbp[4] == '!' || dbp[4] == '!') &&
+ (isspace(dbp[5])))
+ {
+ while (!isspace(*dbp)) dbp++;
+ /* Skip over white space */
+ while (isspace(*dbp)) dbp++;
+ get_scheme ();
+ }
+ }
+}
+
+static
+get_scheme()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ if (*dbp == 0) return;
+ /* Go till you get to white space or a syntactic break */
+ for (cp = dbp+1; *cp && *cp != '(' && *cp != ')' && !isspace(*cp); cp++)
+ continue;
+ /* Null terminate the string there. */
+ c = cp[0];
+ cp[0] = 0;
+ /* Copy the string */
+ strcpy(nambuf, dbp);
+ /* Unterminate the string */
+ cp[0] = c;
+ /* Announce the change */
+ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
+ pfcnt++;
+}
+static get_mcode ();
+Mcode_funcs (fi)
+ FILE *fi;
+{
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+
+ while (*dbp != 0)
+ {
+ /* Skip over white space */
+ while (isspace(*dbp)) dbp++;
+ get_mcode();
+ }
+ }
+}
+
+static
+get_mcode()
+{
+ register char *cp;
+ char c;
+ char nambuf[BUFSIZ];
+
+ if (*dbp == 0) return;
+ /* Go till you get to white space or a syntactic break */
+ for (cp = dbp; *cp && *cp != ':' && *cp != ';' && !isspace(*cp); cp++)
+ continue;
+
+ if(*cp == ':')
+ {
+ /* Null terminate the string there. */
+ c = cp[0];
+ cp[0] = 0;
+ /* Copy the string */
+ strcpy(nambuf, dbp);
+ /* Unterminate the string */
+ cp[0] = c;
+ /* Announce the change */
+ pfnote(nambuf, TRUE, lb.buffer, strlen(lb.buffer), lineno, linecharno);
+ pfcnt++;
+ *dbp = 0;
+ }
+ if (*cp == ';')
+ *dbp = 0;
+ else
+ dbp = cp;
+}
+
+/* Find tags in TeX and LaTeX input files. */
+
+/* TEX_toktab is a table of TeX control sequences that define tags.
+ Each TEX_tabent records one such control sequence. */
+
+struct TEX_tabent
+{
+ char *name;
+ int len;
+};
+
+struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */
+
+/* Default set of control sequences to put into TEX_toktab.
+ The value of environment var TEXTAGS is prepended to this. */
+
+static char *TEX_defenv =
+ ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout";
+
+struct TEX_tabent *TEX_decode_env ();
+
+static char TEX_esc = '\\';
+static char TEX_opgrp = '{';
+static char TEX_clgrp = '}';
+
+/*
+ * TeX/LaTeX scanning loop.
+ */
+
+TEX_funcs (fi)
+ FILE *fi;
+{
+ char *lasthit;
+
+ lineno = 0;
+ charno = 0;
+ pfcnt = 0;
+
+ /* Select either \ or ! as escape character. */
+ TEX_mode (fi);
+
+ /* Initialize token table once from environment. */
+ if (!TEX_toktab)
+ TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
+
+ while (!feof (fi))
+ {
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ lasthit = dbp;
+
+ while (!feof (fi))
+ { /* Scan each line in file */
+ lineno++;
+ linecharno = charno;
+ charno += readline (&lb, fi) + 1;
+ dbp = lb.buffer;
+ lasthit = dbp;
+ while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */
+ {
+ register int i;
+
+ if (! *(++dbp))
+ break;
+ linecharno += dbp - lasthit;
+ lasthit = dbp;
+ i = TEX_Token (lasthit);
+ if (0 <= i)
+ {
+ TEX_getit (lasthit, TEX_toktab[i].len);
+ break; /* We only save a line once */
+ }
+ }
+ }
+ }
+}
+
+#define TEX_LESC '\\'
+#define TEX_SESC '!'
+
+/* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */
+/* chars accordingly. */
+
+TEX_mode (f)
+ FILE *f;
+{
+ int c;
+
+ while ((c = getc (f)) != EOF)
+ if (c == TEX_LESC || c == TEX_SESC)
+ break;
+
+ if (c == TEX_LESC)
+ {
+ TEX_esc = TEX_LESC;
+ TEX_opgrp = '{';
+ TEX_clgrp = '}';
+ }
+ else
+ {
+ TEX_esc = TEX_SESC;
+ TEX_opgrp = '<';
+ TEX_clgrp = '>';
+ }
+ rewind (f);
+}
+
+/* Read environment and prepend it to the default string. */
+/* Build token table. */
+
+struct TEX_tabent *
+TEX_decode_env (evarname, defenv)
+ char *evarname;
+ char *defenv;
+{
+ register char *env, *p;
+ extern char *savenstr (), *index ();
+
+ struct TEX_tabent *tab;
+ int size, i;
+
+ /* Append deafult string to environment. */
+ env = (char *) getenv (evarname);
+ if (!env)
+ env = defenv;
+ else
+ env = concat (env, defenv, "");
+
+ /* Allocate a token table */
+ for (size = 1, p=env; p;)
+ if ((p = index (p, ':')) && *(++p))
+ size++;
+ tab = (struct TEX_tabent *) xmalloc (size * sizeof (struct TEX_tabent));
+
+ /* Unpack environment string into token table. Be careful about */
+ /* zero-length strings (leading ':', "::" and trailing ':') */
+ for (i = 0; *env;)
+ {
+ p = index (env, ':');
+ if (!p) /* End of environment string. */
+ p = env + strlen (env);
+ if (p - env > 0)
+ { /* Only non-zero strings. */
+ tab[i].name = savenstr (env, p - env);
+ tab[i].len = strlen (tab[i].name);
+ i++;
+ }
+ if (*p)
+ env = p + 1;
+ else
+ {
+ tab[i].name = NULL; /* Mark end of table. */
+ tab[i].len = 0;
+ break;
+ }
+ }
+ return tab;
+}
+
+/* Record a tag defined by a TeX command of length LEN and starting at NAME.
+ The name being defined actually starts at (NAME + LEN + 1).
+ But we seem to include the TeX command in the tag name. */
+
+TEX_getit (name, len)
+ char *name;
+ int len;
+{
+ char *p = name + len;
+ char nambuf[BUFSIZ];
+
+ if (*name == 0) return;
+
+ /* Let tag name extend to next group close (or end of line) */
+ while (*p && *p != TEX_clgrp)
+ p++;
+ strncpy (nambuf, name, p - name);
+ nambuf[p - name] = 0;
+
+ pfnote (nambuf, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno);
+ pfcnt++;
+}
+
+/* If the text at CP matches one of the tag-defining TeX command names,
+ return the index of that command in TEX_toktab.
+ Otherwise return -1. */
+
+/* Keep the capital `T' in `Token' for dumb truncating compilers
+ (this distinguishes it from `TEX_toktab' */
+TEX_Token (cp)
+ char *cp;
+{
+ int i;
+
+ for (i = 0; TEX_toktab[i].len > 0; i++)
+ if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0)
+ return i;
+ return -1;
+}
+
+/* Initialize a linebuffer for use */
+
+void
+initbuffer (linebuffer)
+ struct linebuffer *linebuffer;
+{
+ linebuffer->size = 200;
+ linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from `stream' into `linebuffer'.
+ Return the length of the line. */
+
+long
+readline (linebuffer, stream)
+ struct linebuffer *linebuffer;
+ register FILE *stream;
+{
+ char *buffer = linebuffer->buffer;
+ register char *p = linebuffer->buffer;
+ register char *pend = p + linebuffer->size;
+
+ while (1)
+ {
+ int c = getc (stream);
+ if (p == pend)
+ {
+ linebuffer->size *= 2;
+ buffer = (char *) xrealloc (buffer, linebuffer->size);
+ p += buffer - linebuffer->buffer;
+ pend = buffer + linebuffer->size;
+ linebuffer->buffer = buffer;
+ }
+ if (c < 0 || c == '\n')
+ {
+ *p = 0;
+ break;
+ }
+ *p++ = c;
+ }
+
+ return p - buffer;
+}
+
+char *
+savestr(cp)
+ char *cp;
+{
+ return savenstr (cp, strlen (cp));
+}
+
+char *
+savenstr(cp, len)
+ char *cp;
+ int len;
+{
+ register char *dp;
+
+ dp = (char *) xmalloc (len + 1);
+ strncpy (dp, cp, len);
+ dp[len] = '\0';
+ return dp;
+}
+
+/*
+ * Return the ptr in sp at which the character c last
+ * appears; NULL if not found
+ *
+ * Identical to v7 rindex, included for portability.
+ */
+
+char *
+rindex(sp, c)
+ register char *sp, c;
+{
+ register char *r;
+
+ r = NULL;
+ do
+ {
+ if (*sp == c)
+ r = sp;
+ } while (*sp++);
+ return(r);
+}
+
+/*
+ * Return the ptr in sp at which the character c first
+ * appears; NULL if not found
+ *
+ * Identical to v7 index, included for portability.
+ */
+
+char *
+index(sp, c)
+ register char *sp, c;
+{
+ do
+ {
+ if (*sp == c)
+ return (sp);
+ } while (*sp++);
+ return (NULL);
+}
+
+/* Print error message and exit. */
+
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ exit (BAD);
+}
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+error (s1, s2)
+ char *s1, *s2;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, s1, s2);
+ fprintf (stderr, "\n");
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+int
+xmalloc (size)
+ int size;
+{
+ int result = malloc (size);
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+int
+xrealloc (ptr, size)
+ char *ptr;
+ int size;
+{
+ int result = realloc (ptr, size);
+ if (!result)
+ fatal ("virtual memory exhausted");
+ return result;
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes b/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes
new file mode 100644
index 0000000000..324c0d447e
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes
@@ -0,0 +1,568 @@
+From jbw@bigbird.bu.edu Tue Aug 18 08:07:53 1992
+From: jbw@bigbird.bu.edu (Joe Wells)
+Newsgroups: comp.emacs
+Subject: Re: How do I include symbols defined with #define in TAGS ?
+Date: 16 Aug 92 23:27:25 GMT
+Distribution: comp.emacs
+Organization: Boston University Computer Science Department
+In-reply-to: podi@ESD.3Com.COM's message of 14 Aug 92 17:53:29 GMT
+
+In article <podi.713814809@chamundi.NSD.3Com.COM> podi@ESD.3Com.COM (Podibanda Kuruppu) writes:
+
+ Keywords: Symbols defined by #defines in TAGS
+
+ I would greatly appreciate it if someone could tell me if I could
+ include symbols ( defined in .h files with #defines ) in a TAG file.
+
+Enclosed below is an earlier article with my solution to this.
+
+--
+Enjoy,
+
+Joe Wells <jbw@cs.bu.edu>
+Member of the League for Programming Freedom --- send e-mail for details
+
+----------------------------------------------------------------------
+Date: Sat, 4 Apr 92 00:46:52 -0500
+From: jbw@bigbird.bu.edu (Joe Wells)
+Message-Id: <9204040546.AA15208@bigbird.bu.edu>
+To: bug-gnu-emacs@prep.ai.mit.edu
+Subject: numerous bug fixes for etags
+
+Enclosed is a patch with numerous changes for etags. The following are
+the changes and bugs fixed:
+
+1. Improvement: don't waste time calling strncmp (with "struct", "union",
+ "enum", "typedef") if the lengths are different.
+
+2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused
+ things like `{' or `/*' to be ignored, thus severely screwing up the
+ parser. Or it did something horrible, I don't remember for sure.
+
+3. Improvement: record defining occurrences of struct/union/enum tags.
+ This works even if combined with a typedef definition, for example:
+
+ typedef struct XXX {
+ .....
+ } YYY;
+
+4. Bug: when a tag token was the last item on the line before the newline
+ character, garbage would be seen as the token. This is because when a
+ NUL was seen in the buffer the buffer was replaced with the next line.
+
+5. Bug: tag tokens immediately followed by a `{' with no intervening space
+ were not recorded. This was only a problem because of improvement 3
+ above.
+
+6. Bug: a newline in the middle of a comment zeroed the `number' variable.
+ (Just for good measure I made it not zero `number' in strings even when
+ the newline is not preceded by `\', in case someone wants to run etags
+ on illegal code :-) (`number' is used only on lines that begin with
+ `#'.)
+
+7. Bug: handling of #define lines was severely broken. I don't actually
+ remember what etags did with them, but it was really bad. It now
+ records macro definitions.
+
+8. Bug: when a tag token was the last item on the line except for
+ whitespace, etags would replace the contents of the line buffer and
+ then later do various string comparisons and inspections against
+ garbage values instead of against the token. Fixing this required
+ copying the token into a buffer. (This is roughly the same as bug 4
+ above, but in a different function.)
+
+9. Bug: when a tag token was the last item on the line before the newline
+ (and under various other circumstances), etags would skip over the NUL
+ in the buffer and skip to the first non-whitespace character in the
+ buffer.
+
+10. Improvement (possibly bug fix): parse typedefs even when we aren't
+ going to print them out. I seem to remember that this fixed some bug,
+ but I don't remember the specific case that would trigger the bug.
+
+11. An unfinished attempt to detect and record global variable
+ definitions.
+
+The changes are to the 18.57 version of etags, but the only change in
+18.58 to the C code handling is to initialize some variables when starting
+on a new file, so these changes are orthogonal.
+
+--
+Enjoy,
+
+Joe Wells <jbw@cs.bu.edu>
+
+Member of the League for Programming Freedom --- send e-mail for details
+
+----------------------------------------------------------------------
+--- etags.c-dist Tue Jan 8 14:08:38 1991
++++ etags.c Sat Apr 4 00:41:22 1992
+@@ -62,7 +62,10 @@
+
+ /* cause token checking for typedef, struct, union, enum to distinguish
+ keywords from identifier-prefixes (e.g. struct vs struct_tag). */
+-#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
++#define istoken(s, t, len) \
++ (((len) == (sizeof (t) -1)) && \
++ ((strncmp(s, t, len)) == 0) && \
++ (endtoken(*((s)+(len)))))
+
+ struct nd_st { /* sorting structure */
+ char *name; /* function or type name */
+@@ -505,6 +508,7 @@
+ {
+ register char *fp;
+ register NODE *np;
++ char save;
+ char *altname;
+ char tem[51];
+
+@@ -538,6 +542,7 @@
+ np->left = np->right = 0;
+ if (eflag)
+ {
++ save = linestart[linelen];
+ linestart[linelen] = 0;
+ }
+ else if (xflag == 0)
+@@ -546,6 +551,7 @@
+ linestart = tem;
+ }
+ np->pat = savestr (linestart);
++ linestart[linelen] = save;
+ if (head == NULL)
+ head = np;
+ else
+@@ -725,6 +731,17 @@
+ number = 0; \
+ }
+
++/* These two are part of a never-finished attempt to record global */
++/* variable definitions. This is nearly impossible in C without the full */
++/* power of a C compiler due to C's stupid grammar. */
++logical infunc;
++int idents_in_decl;
++
++/* indicates whether the next token (if any) is the tag corresponding to */
++/* `struct', `union', or `enum' */
++logical next_token_is_tag;
++
++
+ C_entries ()
+ {
+ register int c;
+@@ -731,6 +748,15 @@
+ register char *token, *tp, *lp;
+ logical incomm, inquote, inchar, midtoken;
+ int level;
++
++ /* there are certain things that must be done when the end of line is */
++ /* encountered, but they must be delayed until after other things are */
++ /* done. */
++ logical new_line_flag;
++
++ /* same as new_line_flag for left braces. */
++ logical left_brace_flag;
++
+ char tok[BUFSIZ];
+
+ lineno = 0;
+@@ -739,17 +765,22 @@
+ *lp = 0;
+
+ number = 0;
+- gotone = midtoken = inquote = inchar = incomm = FALSE;
++ gotone = midtoken = inquote = inchar = incomm = infunc = FALSE;
++ new_line_flag = FALSE;
++ left_brace_flag = FALSE;
+ level = 0;
++ idents_in_decl = 0;
++ next_token_is_tag = FALSE;
+
+ while (!feof (inf))
+ {
+ c = *lp++;
+ if (c == 0)
+- {
+- CNL;
+- gotone = FALSE;
+- }
++ new_line_flag = TRUE;
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ if (c == '\\')
+ {
+ c = *lp++;
+@@ -756,15 +787,18 @@
+ if (c == 0)
+ CNL_SAVE_NUMBER;
+ c = ' ';
++ /* is this correct? I thought escaped newlines disappeared even */
++ /* before the token breaker got to see things. */
+ }
+ else if (incomm)
+ {
++ new_line_flag = FALSE;
+ if (c == '*')
+ {
+ while ((c = *lp++) == '*')
+ continue;
+ if (c == 0)
+- CNL;
++ CNL_SAVE_NUMBER;
+ if (c == '/')
+ incomm = FALSE;
+ }
+@@ -771,6 +805,7 @@
+ }
+ else if (inquote)
+ {
++ new_line_flag = FALSE;
+ /*
+ * Too dumb to know about \" not being magic, but
+ * they usually occur in pairs anyway.
+@@ -781,6 +816,7 @@
+ }
+ else if (inchar)
+ {
++ new_line_flag = FALSE;
+ if (c == '\'')
+ inchar = FALSE;
+ continue;
+@@ -809,8 +845,8 @@
+ {
+ tydef=middle;
+ }
+- level++;
+- continue;
++ left_brace_flag = TRUE;
++ break;
+ case '}':
+ if (lp == lb.buffer + 1)
+ level = 0; /* reset */
+@@ -820,8 +856,17 @@
+ {
+ tydef=end;
+ }
++ if (level == 0 && infunc)
++ {
++ idents_in_decl = 0;
++ infunc = FALSE;
++ }
+ continue;
+ }
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ if (!level && !inquote && !incomm && gotone == FALSE)
+ {
+ if (midtoken)
+@@ -852,6 +897,11 @@
+ tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb1.buffer, endpos, line, linestart);
++#ifdef DEBUG
++ fprintf (stderr,
++ "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n",
++ f, infunc, tok, lb1.buffer);
++#endif /* DEBUG */
+ }
+ else
+ {
+@@ -858,8 +908,15 @@
+ strncpy (tok, token, tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb.buffer, endpos, line, linestart);
++#ifdef DEBUG
++ fprintf (stderr,
++ "f: %d, infunc %d, tok: %s\nlb.buffer: %s\n",
++ f, infunc, tok, lb.buffer);
++#endif /* DEBUG */
+ }
+ gotone = f; /* function */
++ if (f)
++ infunc = TRUE;
+ }
+ midtoken = FALSE;
+ token = lp - 1;
+@@ -873,8 +930,32 @@
+ midtoken = TRUE;
+ }
+ }
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
++ if (left_brace_flag)
++ {
++ left_brace_flag = FALSE;
++ next_token_is_tag = FALSE;
++ level++;
++ }
++ if (new_line_flag)
++ {
++ new_line_flag = FALSE;
++ number = 0;
++ gotone = FALSE;
++ }
++ if (lp > lb.buffer && lp[-1] == 0)
++ CNL_SAVE_NUMBER;
+ if (c == ';' && tydef==end) /* clean with typedefs */
+ tydef=none;
++ if (c == ';' && level == 0 && !infunc)
++ idents_in_decl = 0;
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ }
+ }
+
+@@ -891,70 +972,176 @@
+ reg char *lp = *lpp;
+ reg char c;
+ static logical next_token_is_func;
++
++ /* indicates that the next token will be a macro defined with #define */
++ static logical next_token_is_macro;
++
+ logical firsttok; /* T if have seen first token in ()'s */
+- int bad, win;
++ int bad = FALSE, win = FALSE;
++ int length = (lp - 1) - token;
++
++ /* used to keep a copy of the token when we have to fill the line buffer */
++ /* with the contents of the next line */
++ static char *tok_buffer = NULL;
++ static long tok_buffer_size = 0;
+
+ *f = 1; /* a function */
+ c = lp[-1];
+- bad = FALSE;
+ if (!number)
+ { /* space is not allowed in macro defs */
+- while (iswhite(c))
++ while ((c == 0) || iswhite(c))
+ {
+- c = *lp++;
+- if (c == 0)
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n",
++ token, c, lp - token);
++#endif /* DEBUG */
++ while (c == 0)
+ {
+ if (feof (inf))
+- break;
++ goto break_while_1;
++ if (token != tok_buffer)
++ {
++ if (length + 1 > tok_buffer_size)
++ if (tok_buffer_size == 0)
++ {
++ tok_buffer_size = length + 1;
++ tok_buffer = (char *) xmalloc (tok_buffer_size);
++ }
++ else
++ {
++ tok_buffer_size = length + 1;
++ tok_buffer =
++ (char *) xrealloc (tok_buffer, tok_buffer_size);
++ }
++ strncpy (tok_buffer, token, length);
++ tok_buffer[length] = '\0';
++ token = tok_buffer;
++ }
+ CNL;
++ c = *lp++;
+ }
++ while ((c != 0) && iswhite(c))
++ c = *lp++;
+ }
+- /* the following tries to make it so that a #define a b(c) */
+- /* doesn't count as a define of b. */
++ break_while_1:
++ ;
+ }
+ else
+ {
++ /* the following tries to make it so that a #define a b(c) */
++ /* doesn't count as a define of b. */
+ number++;
+- if (number >= 4 || (number==2 && strncmp (token, "define", 6)))
+- {
+- gotone = TRUE;
+- badone:
++#ifdef DEBUG
++ fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n",
++ number, next_token_is_macro, token);
++#endif /* DEBUG */
++ if (number == 2 && strncmp (token, "define", 6) == 0)
++ next_token_is_macro = TRUE;
++ else if (number == 3 && next_token_is_macro)
++ {
++ next_token_is_macro = FALSE;
++ while ((c != 0) && iswhite(c))
++ {
++#ifdef DEBUG
++ fprintf (stderr, "c: %c, %d\n", c, c);
++#endif /* DEBUG */
++ c = *lp++;
++ }
++#ifdef DEBUG
++ fprintf (stderr, "c: %c, %d\n", c, c);
++#endif /* DEBUG */
++ if (c == 0) /* ignore plain "#define FLAG" */
+ bad = TRUE;
++ else
++ win = TRUE;
++ /* speed up skipping the rest of this line */
++ gotone = TRUE;
++ /* never treat a macro as a function, because it doesn't have a */
++ /* function body, which is what "f" really stands for (now). */
++ *f = FALSE;
+ goto ret;
+ }
++ else
++ /* speed up skipping the rest of this line */
++ gotone = TRUE;
++ goto badone;
+ }
++ idents_in_decl ++;
++#ifdef DEBUG
++ fprintf (stderr,
++ "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
++ length + 5, token);
++#endif /* DEBUG */
+ /* check for the typedef cases */
+- if (tflag && istoken(token, "typedef", 7))
++ if (istoken (token, "typedef", length))
+ {
+ tydef=begin;
+ goto badone;
+ }
+- if (tydef==begin && (istoken(token, "struct", 6) ||
+- istoken(token, "union", 5) || istoken(token, "enum", 4)))
+- {
++#ifdef DEBUG
++ fprintf (stderr, "D\n");
++#endif /* DEBUG */
++ if (istoken (token, "struct", length) ||
++ istoken (token, "union", length) ||
++ istoken (token, "enum", length))
++ {
++ next_token_is_tag = 1;
++#ifdef DEBUG
++ fprintf (stderr, "A: token: %s\n", token);
++#endif /* DEBUG */
++ if (tydef == begin)
+ tydef=tag_ok;
+ goto badone;
+ }
+- if (tydef==tag_ok)
++ else if (next_token_is_tag)
+ {
++#ifdef DEBUG
++ fprintf (stderr, "B: token: %s, c: [%c]\n", token, c);
++#endif /* DEBUG */
++ if (tydef==tag_ok)
+ tydef=middle;
+- goto badone;
++ next_token_is_tag = 0;
++ *f = 0;
++ /* only notice when a tag is being defined, not when it is merely */
++ /* being used. */
++ if (c == '{')
++ win = TRUE;
++ else
++ bad = TRUE;
++ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "E\n");
++#endif /* DEBUG */
+ if (tydef==begin) /* e.g. typedef ->int<- */
+ {
+ tydef=end;
+ goto badone;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "F\n");
++#endif /* DEBUG */
+ if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
+ {
+ tydef=end;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "G\n");
++#endif /* DEBUG */
+ if (tydef==end)
+ {
+ *f = 0;
+- win = 1;
++#ifdef DEBUG
++ fprintf (stderr, "C token: %s\n", token);
++#endif /* DEBUG */
++ win = tflag;
+ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "H\n");
++#endif /* DEBUG */
+ /* Detect GNUmacs's function-defining macros. */
+ if (!number && !strncmp (token, "DEF", 3))
+
+@@ -962,6 +1149,9 @@
+ next_token_is_func = 1;
+ goto badone;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "I\n");
++#endif /* DEBUG */
+ if (next_token_is_func)
+ {
+ next_token_is_func = 0;
+@@ -968,9 +1158,15 @@
+ win = 1;
+ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "J\n");
++#endif /* DEBUG */
+ if (c != '(')
+ goto badone;
+ firsttok = FALSE;
++#ifdef DEBUG
++ fprintf (stderr, "K\n");
++#endif /* DEBUG */
+ while ((c = *lp++) != ')')
+ {
+ if (c == 0)
+@@ -999,9 +1195,20 @@
+ }
+ }
+ win = isgood (c);
++
+ ret:
++#ifdef DEBUG
++ fprintf (stderr,
++ "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
++ length + 5, token);
++#endif /* DEBUG */
+ *lpp = lp - 1;
+ return !bad && win;
++
++ badone:
++ bad = TRUE;
++ goto ret;
+ }
+
+ getline (atchar)
+----------------------------------------------------------------------
+
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes b/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes
new file mode 100644
index 0000000000..242e4e1002
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes
@@ -0,0 +1,545 @@
+From jbw@bigbird.bu.edu Sun Apr 5 14:58:19 1992
+From: jbw@bigbird.bu.edu (Joe Wells)
+Newsgroups: gnu.emacs.bug
+Subject: numerous bug fixes for etags
+Date: 3 Apr 92 19:46:52 GMT
+Distribution: gnu
+Organization: GNUs Not Usenet
+
+Enclosed is a patch with numerous changes for etags. The following are
+the changes and bugs fixed:
+
+1. Improvement: don't waste time calling strncmp (with "struct", "union",
+ "enum", "typedef") if the lengths are different.
+
+2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused
+ things like `{' or `/*' to be ignored, thus severely screwing up the
+ parser. Or it did something horrible, I don't remember for sure.
+
+3. Improvement: record defining occurrences of struct/union/enum tags.
+ This works even if combined with a typedef definition, for example:
+
+ typedef struct XXX {
+ .....
+ } YYY;
+
+4. Bug: when a tag token was the last item on the line before the newline
+ character, garbage would be seen as the token. This is because when a
+ NUL was seen in the buffer the buffer was replaced with the next line.
+
+5. Bug: tag tokens immediately followed by a `{' with no intervening space
+ were not recorded. This was only a problem because of improvement 3
+ above.
+
+6. Bug: a newline in the middle of a comment zeroed the `number' variable.
+ (Just for good measure I made it not zero `number' in strings even when
+ the newline is not preceded by `\', in case someone wants to run etags
+ on illegal code :-) (`number' is used only on lines that begin with
+ `#'.)
+
+7. Bug: handling of #define lines was severely broken. I don't actually
+ remember what etags did with them, but it was really bad. It now
+ records macro definitions.
+
+8. Bug: when a tag token was the last item on the line except for
+ whitespace, etags would replace the contents of the line buffer and
+ then later do various string comparisons and inspections against
+ garbage values instead of against the token. Fixing this required
+ copying the token into a buffer. (This is roughly the same as bug 4
+ above, but in a different function.)
+
+9. Bug: when a tag token was the last item on the line before the newline
+ (and under various other circumstances), etags would skip over the NUL
+ in the buffer and skip to the first non-whitespace character in the
+ buffer.
+
+10. Improvement (possibly bug fix): parse typedefs even when we aren't
+ going to print them out. I seem to remember that this fixed some bug,
+ but I don't remember the specific case that would trigger the bug.
+
+11. An unfinished attempt to detect and record global variable
+ definitions.
+
+The changes are to the 18.57 version of etags, but the only change in
+18.58 to the C code handling is to initialize some variables when starting
+on a new file, so these changes are orthogonal.
+
+--
+Enjoy,
+
+Joe Wells <jbw@cs.bu.edu>
+
+Member of the League for Programming Freedom --- send e-mail for details
+
+----------------------------------------------------------------------
+--- etags.c-dist Tue Jan 8 14:08:38 1991
++++ etags.c Sat Apr 4 00:41:22 1992
+@@ -62,7 +62,10 @@
+
+ /* cause token checking for typedef, struct, union, enum to distinguish
+ keywords from identifier-prefixes (e.g. struct vs struct_tag). */
+-#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
++#define istoken(s, t, len) \
++ (((len) == (sizeof (t) -1)) && \
++ ((strncmp(s, t, len)) == 0) && \
++ (endtoken(*((s)+(len)))))
+
+ struct nd_st { /* sorting structure */
+ char *name; /* function or type name */
+@@ -505,6 +508,7 @@
+ {
+ register char *fp;
+ register NODE *np;
++ char save;
+ char *altname;
+ char tem[51];
+
+@@ -538,6 +542,7 @@
+ np->left = np->right = 0;
+ if (eflag)
+ {
++ save = linestart[linelen];
+ linestart[linelen] = 0;
+ }
+ else if (xflag == 0)
+@@ -546,6 +551,7 @@
+ linestart = tem;
+ }
+ np->pat = savestr (linestart);
++ linestart[linelen] = save;
+ if (head == NULL)
+ head = np;
+ else
+@@ -725,6 +731,17 @@
+ number = 0; \
+ }
+
++/* These two are part of a never-finished attempt to record global */
++/* variable definitions. This is nearly impossible in C without the full */
++/* power of a C compiler due to C's stupid grammar. */
++logical infunc;
++int idents_in_decl;
++
++/* indicates whether the next token (if any) is the tag corresponding to */
++/* `struct', `union', or `enum' */
++logical next_token_is_tag;
++
++
+ C_entries ()
+ {
+ register int c;
+@@ -731,6 +748,15 @@
+ register char *token, *tp, *lp;
+ logical incomm, inquote, inchar, midtoken;
+ int level;
++
++ /* there are certain things that must be done when the end of line is */
++ /* encountered, but they must be delayed until after other things are */
++ /* done. */
++ logical new_line_flag;
++
++ /* same as new_line_flag for left braces. */
++ logical left_brace_flag;
++
+ char tok[BUFSIZ];
+
+ lineno = 0;
+@@ -739,17 +765,22 @@
+ *lp = 0;
+
+ number = 0;
+- gotone = midtoken = inquote = inchar = incomm = FALSE;
++ gotone = midtoken = inquote = inchar = incomm = infunc = FALSE;
++ new_line_flag = FALSE;
++ left_brace_flag = FALSE;
+ level = 0;
++ idents_in_decl = 0;
++ next_token_is_tag = FALSE;
+
+ while (!feof (inf))
+ {
+ c = *lp++;
+ if (c == 0)
+- {
+- CNL;
+- gotone = FALSE;
+- }
++ new_line_flag = TRUE;
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ if (c == '\\')
+ {
+ c = *lp++;
+@@ -756,15 +787,18 @@
+ if (c == 0)
+ CNL_SAVE_NUMBER;
+ c = ' ';
++ /* is this correct? I thought escaped newlines disappeared even */
++ /* before the token breaker got to see things. */
+ }
+ else if (incomm)
+ {
++ new_line_flag = FALSE;
+ if (c == '*')
+ {
+ while ((c = *lp++) == '*')
+ continue;
+ if (c == 0)
+- CNL;
++ CNL_SAVE_NUMBER;
+ if (c == '/')
+ incomm = FALSE;
+ }
+@@ -771,6 +805,7 @@
+ }
+ else if (inquote)
+ {
++ new_line_flag = FALSE;
+ /*
+ * Too dumb to know about \" not being magic, but
+ * they usually occur in pairs anyway.
+@@ -781,6 +816,7 @@
+ }
+ else if (inchar)
+ {
++ new_line_flag = FALSE;
+ if (c == '\'')
+ inchar = FALSE;
+ continue;
+@@ -809,8 +845,8 @@
+ {
+ tydef=middle;
+ }
+- level++;
+- continue;
++ left_brace_flag = TRUE;
++ break;
+ case '}':
+ if (lp == lb.buffer + 1)
+ level = 0; /* reset */
+@@ -820,8 +856,17 @@
+ {
+ tydef=end;
+ }
++ if (level == 0 && infunc)
++ {
++ idents_in_decl = 0;
++ infunc = FALSE;
++ }
+ continue;
+ }
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ if (!level && !inquote && !incomm && gotone == FALSE)
+ {
+ if (midtoken)
+@@ -852,6 +897,11 @@
+ tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb1.buffer, endpos, line, linestart);
++#ifdef DEBUG
++ fprintf (stderr,
++ "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n",
++ f, infunc, tok, lb1.buffer);
++#endif /* DEBUG */
+ }
+ else
+ {
+@@ -858,8 +908,15 @@
+ strncpy (tok, token, tp-token+1);
+ tok[tp-token+1] = 0;
+ pfnote(tok, f, lb.buffer, endpos, line, linestart);
++#ifdef DEBUG
++ fprintf (stderr,
++ "f: %d, infunc %d, tok: %s\nlb.buffer: %s\n",
++ f, infunc, tok, lb.buffer);
++#endif /* DEBUG */
+ }
+ gotone = f; /* function */
++ if (f)
++ infunc = TRUE;
+ }
+ midtoken = FALSE;
+ token = lp - 1;
+@@ -873,8 +930,32 @@
+ midtoken = TRUE;
+ }
+ }
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
++ if (left_brace_flag)
++ {
++ left_brace_flag = FALSE;
++ next_token_is_tag = FALSE;
++ level++;
++ }
++ if (new_line_flag)
++ {
++ new_line_flag = FALSE;
++ number = 0;
++ gotone = FALSE;
++ }
++ if (lp > lb.buffer && lp[-1] == 0)
++ CNL_SAVE_NUMBER;
+ if (c == ';' && tydef==end) /* clean with typedefs */
+ tydef=none;
++ if (c == ';' && level == 0 && !infunc)
++ idents_in_decl = 0;
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
++#endif /* DEBUG */
+ }
+ }
+
+@@ -891,70 +972,176 @@
+ reg char *lp = *lpp;
+ reg char c;
+ static logical next_token_is_func;
++
++ /* indicates that the next token will be a macro defined with #define */
++ static logical next_token_is_macro;
++
+ logical firsttok; /* T if have seen first token in ()'s */
+- int bad, win;
++ int bad = FALSE, win = FALSE;
++ int length = (lp - 1) - token;
++
++ /* used to keep a copy of the token when we have to fill the line buffer */
++ /* with the contents of the next line */
++ static char *tok_buffer = NULL;
++ static long tok_buffer_size = 0;
+
+ *f = 1; /* a function */
+ c = lp[-1];
+- bad = FALSE;
+ if (!number)
+ { /* space is not allowed in macro defs */
+- while (iswhite(c))
++ while ((c == 0) || iswhite(c))
+ {
+- c = *lp++;
+- if (c == 0)
++#ifdef DEBUG
++ if (next_token_is_tag)
++ fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n",
++ token, c, lp - token);
++#endif /* DEBUG */
++ while (c == 0)
+ {
+ if (feof (inf))
+- break;
++ goto break_while_1;
++ if (token != tok_buffer)
++ {
++ if (length + 1 > tok_buffer_size)
++ if (tok_buffer_size == 0)
++ {
++ tok_buffer_size = length + 1;
++ tok_buffer = (char *) xmalloc (tok_buffer_size);
++ }
++ else
++ {
++ tok_buffer_size = length + 1;
++ tok_buffer =
++ (char *) xrealloc (tok_buffer, tok_buffer_size);
++ }
++ strncpy (tok_buffer, token, length);
++ tok_buffer[length] = '\0';
++ token = tok_buffer;
++ }
+ CNL;
++ c = *lp++;
+ }
++ while ((c != 0) && iswhite(c))
++ c = *lp++;
+ }
+- /* the following tries to make it so that a #define a b(c) */
+- /* doesn't count as a define of b. */
++ break_while_1:
++ ;
+ }
+ else
+ {
++ /* the following tries to make it so that a #define a b(c) */
++ /* doesn't count as a define of b. */
+ number++;
+- if (number >= 4 || (number==2 && strncmp (token, "define", 6)))
+- {
+- gotone = TRUE;
+- badone:
++#ifdef DEBUG
++ fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n",
++ number, next_token_is_macro, token);
++#endif /* DEBUG */
++ if (number == 2 && strncmp (token, "define", 6) == 0)
++ next_token_is_macro = TRUE;
++ else if (number == 3 && next_token_is_macro)
++ {
++ next_token_is_macro = FALSE;
++ while ((c != 0) && iswhite(c))
++ {
++#ifdef DEBUG
++ fprintf (stderr, "c: %c, %d\n", c, c);
++#endif /* DEBUG */
++ c = *lp++;
++ }
++#ifdef DEBUG
++ fprintf (stderr, "c: %c, %d\n", c, c);
++#endif /* DEBUG */
++ if (c == 0) /* ignore plain "#define FLAG" */
+ bad = TRUE;
++ else
++ win = TRUE;
++ /* speed up skipping the rest of this line */
++ gotone = TRUE;
++ /* never treat a macro as a function, because it doesn't have a */
++ /* function body, which is what "f" really stands for (now). */
++ *f = FALSE;
+ goto ret;
+ }
++ else
++ /* speed up skipping the rest of this line */
++ gotone = TRUE;
++ goto badone;
+ }
++ idents_in_decl ++;
++#ifdef DEBUG
++ fprintf (stderr,
++ "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
++ length + 5, token);
++#endif /* DEBUG */
+ /* check for the typedef cases */
+- if (tflag && istoken(token, "typedef", 7))
++ if (istoken (token, "typedef", length))
+ {
+ tydef=begin;
+ goto badone;
+ }
+- if (tydef==begin && (istoken(token, "struct", 6) ||
+- istoken(token, "union", 5) || istoken(token, "enum", 4)))
+- {
++#ifdef DEBUG
++ fprintf (stderr, "D\n");
++#endif /* DEBUG */
++ if (istoken (token, "struct", length) ||
++ istoken (token, "union", length) ||
++ istoken (token, "enum", length))
++ {
++ next_token_is_tag = 1;
++#ifdef DEBUG
++ fprintf (stderr, "A: token: %s\n", token);
++#endif /* DEBUG */
++ if (tydef == begin)
+ tydef=tag_ok;
+ goto badone;
+ }
+- if (tydef==tag_ok)
++ else if (next_token_is_tag)
+ {
++#ifdef DEBUG
++ fprintf (stderr, "B: token: %s, c: [%c]\n", token, c);
++#endif /* DEBUG */
++ if (tydef==tag_ok)
+ tydef=middle;
+- goto badone;
++ next_token_is_tag = 0;
++ *f = 0;
++ /* only notice when a tag is being defined, not when it is merely */
++ /* being used. */
++ if (c == '{')
++ win = TRUE;
++ else
++ bad = TRUE;
++ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "E\n");
++#endif /* DEBUG */
+ if (tydef==begin) /* e.g. typedef ->int<- */
+ {
+ tydef=end;
+ goto badone;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "F\n");
++#endif /* DEBUG */
+ if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
+ {
+ tydef=end;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "G\n");
++#endif /* DEBUG */
+ if (tydef==end)
+ {
+ *f = 0;
+- win = 1;
++#ifdef DEBUG
++ fprintf (stderr, "C token: %s\n", token);
++#endif /* DEBUG */
++ win = tflag;
+ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "H\n");
++#endif /* DEBUG */
+ /* Detect GNUmacs's function-defining macros. */
+ if (!number && !strncmp (token, "DEF", 3))
+
+@@ -962,6 +1149,9 @@
+ next_token_is_func = 1;
+ goto badone;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "I\n");
++#endif /* DEBUG */
+ if (next_token_is_func)
+ {
+ next_token_is_func = 0;
+@@ -968,9 +1158,15 @@
+ win = 1;
+ goto ret;
+ }
++#ifdef DEBUG
++ fprintf (stderr, "J\n");
++#endif /* DEBUG */
+ if (c != '(')
+ goto badone;
+ firsttok = FALSE;
++#ifdef DEBUG
++ fprintf (stderr, "K\n");
++#endif /* DEBUG */
+ while ((c = *lp++) != ')')
+ {
+ if (c == 0)
+@@ -999,9 +1195,20 @@
+ }
+ }
+ win = isgood (c);
++
+ ret:
++#ifdef DEBUG
++ fprintf (stderr,
++ "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
++ length + 5, token);
++#endif /* DEBUG */
+ *lpp = lp - 1;
+ return !bad && win;
++
++ badone:
++ bad = TRUE;
++ goto ret;
+ }
+
+ getline (atchar)
+----------------------------------------------------------------------
+
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile
new file mode 100644
index 0000000000..cc855bd99e
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile
@@ -0,0 +1,7 @@
+BuildPgmFromOneCFile(msub)
+
+InstallBinaryTarget(msub,$(INSTBINDIR))
+
+CDependTarget( $(SRCS_C) )
+
+RunStdTest(msub001,msub,-f test.makefile testfile -o1 test.stdout)
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c
new file mode 100644
index 0000000000..dccefa990f
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c
@@ -0,0 +1,520 @@
+/*
+ msub - Read file(s) and perform substitutions using values of
+ variables defined in makefile.
+
+ Syntax: msub [-f makefile] [file ...]
+
+ Multiple -f options may be given.
+
+ 27 Mar 1990 Paul DuBois dubois@primate.wisc.edu
+
+ 27 Mar 1990 V1.0. Created.
+*/
+
+# include <stdio.h>
+# include <ctype.h>
+
+
+# define true (1)
+# define false (0)
+
+
+extern char *calloc (), *strcpy ();
+
+
+char *NewString();
+
+
+typedef struct Def Def;
+
+struct Def
+{
+ char *var; /* variable name */
+ char *val; /* variable value */
+ int simple; /* whether value has been expanded */
+ Def *nextDef; /* next definition in list */
+};
+
+
+char *usage = "Usage: msub [ -f makefile ] file";
+char *makefile = NULL;
+Def *defList = NULL; /* list of definitions */
+int nDefs = 0; /* number of definitions */
+int changes;
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+FILE *f;
+Def *dp;
+int i, pass;
+
+ --argc;
+ ++argv;
+
+ while (argc > 0 && argv[0][0] == '-')
+ {
+ if (strcmp (argv[0], "-f") == 0)
+ {
+ if (argc < 2)
+ panic (usage);
+ if ((f = fopen (makefile = argv[1], "r")) == NULL)
+ panic ("Can't open makefile");
+ ReadMake (f);
+ fclose (f);
+ argc -= 2;
+ argv += 2;
+ }
+ else
+ panic (usage); /* bad flag */
+ }
+
+ if (makefile == NULL) /* no -f options given */
+ {
+ if ((f = fopen ("makefile", "r")) == NULL)
+ {
+ if ((f = fopen ("Makefile", "r")) == NULL)
+ panic ("Can't open makefile");
+ }
+ ReadMake (f);
+ fclose (f);
+ }
+
+ EncodeEscapes ();
+
+ /* determine which values need expanding */
+ for (dp = defList; dp != NULL; dp = dp->nextDef)
+ dp->simple = !FindVarRef (dp->val, NULL, NULL, false);
+
+ /* expand values to eliminate embedded var references */
+ for (pass = 0; pass < nDefs; pass++)
+ {
+ changes = 0;
+ for (dp = defList; dp != NULL; dp = dp->nextDef)
+ {
+ if (!dp->simple)
+ Expand (dp);
+ }
+ if (changes == 0) /* loop while values expand */
+ break;
+ }
+
+ /* sanity check: shouldn't have to make more than nDefs passes */
+ if (pass >= nDefs)
+ panic ("Too many expansion passes. Something's wrong!");
+
+ DecodeEscapes ();
+
+ /* partain addition:
+ args of form "foo=bar" are taken to be defs to add in
+ */
+ while (argc > 0 && strchr(argv[0], '=') && isalpha(argv[0][0]))
+ {
+ char name[BUFSIZ], *np, *p;
+ int len;
+ p = argv[0];
+ /* copied from below */
+ np = name;
+ while (isalnum (*p) || *p == '_')
+ *np++ = *p++;
+ *np = '\0';
+ while (isspace (*p)) /* skip whitespace */
+ ++p;
+ if (*p++ == '=') /* it's a definition */
+ {
+ /* skip leading/trailing whitespace */
+ while (isspace (*p))
+ ++p;
+ len = strlen (p);
+ while (len > 0 && isspace (p[len-1]))
+ p[--len] = '\0';
+ AddDef (name, p, 1);
+ /* find var refs in value -- NUKED */
+ /* FindAllVarRefs (p); */
+ /* also NUKED: continue; */
+ }
+ /* end of: copied from below */
+ --argc;
+ ++argv;
+ }
+ /* end of partain addition */
+
+ /* read source file(s) and perform substitutions */
+ if (argc == 0)
+ DoSub (stdin);
+ else while (argc > 0)
+ {
+ if ((f = fopen (*argv, "r")) == NULL)
+ {
+ fprintf (stderr, "Can't open \"%s\". ", *argv);
+ panic ("Quitting.");
+ }
+ DoSub (f);
+ fclose (f);
+ --argc;
+ ++argv;
+ }
+
+ exit (0);
+}
+
+
+/*
+ Read a makefile.
+*/
+
+ReadMake (f)
+FILE *f;
+{
+char input[BUFSIZ * 4], name[BUFSIZ], *p, *np;
+int i, len;
+
+ while (GetLine (f, input)) /* get line, check whether def'n */
+ {
+ for (p = input; isspace (*p); p++) { /* nop */ }
+ if (*p == '#' || *p == '\0') /* comment or blank line */
+ continue;
+ if (isalpha (*p)) /* look for var name */
+ {
+ np = name;
+ while (isalnum (*p) || *p == '_')
+ *np++ = *p++;
+ *np = '\0';
+ while (isspace (*p)) /* skip whitespace */
+ ++p;
+ if (*p++ == '=') /* it's a definition */
+ {
+ /* skip leading/trailing whitespace */
+ while (isspace (*p))
+ ++p;
+ len = strlen (p);
+ while (len > 0 && isspace (p[len-1]))
+ p[--len] = '\0';
+ AddDef (name, p, 1);
+ /* find var refs in value */
+ FindAllVarRefs (p);
+ continue;
+ }
+ }
+ /* not a definition; find var refs anywhere in line */
+ FindAllVarRefs (input);
+ }
+}
+
+
+/*
+ Find definition by variable name.
+*/
+
+Def *FindDefByVar (s)
+char *s;
+{
+Def *dp;
+
+ for (dp = defList; dp != NULL; dp = dp->nextDef)
+ {
+ if (strcmp (dp->var, s) == 0)
+ return (dp);
+ }
+ return (NULL);
+}
+
+
+/*
+ Add a definition. If the name hasn't been seen yet, create a new
+ definition on the list. If the name has been seen, and replace is
+ non-zero, replace the current value with the new one. (replace will
+ be zero if we're just adding a variable which is known by its being
+ referenced somewhere.)
+*/
+
+AddDef (name, value, replace)
+char *name, *value;
+int replace;
+{
+Def *dp;
+
+ if ((dp = FindDefByVar (name)) == NULL)
+ {
+ if ((dp = (Def *) calloc (1, sizeof (Def))) == NULL)
+ panic ("AddDef: out of memory");
+ dp->var = NewString (name);
+ dp->val = NewString (value);
+ dp->simple = 0; /* assume not */
+ dp->nextDef = defList;
+ defList = dp;
+ ++nDefs;
+ }
+ else if (replace)
+ {
+ free (dp->val);
+ dp->val = NewString (value);
+ }
+}
+
+
+/*
+ Replace instances of '$$' with a single ^A.
+*/
+
+EncodeEscapes ()
+{
+Def *dp;
+char *p, *q;
+
+ for (dp = defList; dp != NULL; dp = dp->nextDef)
+ {
+ for (p = q = dp->val; *p != '\0'; p++, q++)
+ {
+ *q = *p;
+ if (*p == '$' && *(p+1) == '$')
+ {
+ *q = '\01';
+ p++;
+ }
+ }
+ *q = '\0';
+ }
+}
+
+
+/*
+ Replace instances of ^A with a '$'.
+*/
+
+DecodeEscapes ()
+{
+Def *dp;
+char *p;
+
+ for (dp = defList; dp != NULL; dp = dp->nextDef)
+ {
+ for (p = dp->val; *p != '\0'; p++)
+ {
+ if (*p == '\01')
+ *p = '$';
+ }
+ }
+}
+
+
+/*
+ Find variable reference in variable value. begin is set to
+ the index of the '$' and end is set to the index of the closing
+ delimiter. (If either is NULL, it is not set.)
+
+ recogEsc is non-zero (true) if '$$' is recognized as an escaped '$'
+ and skipped. It will be true during initial searching for var refs
+ and while substituting in source files, false while expanding variable
+ values.
+
+ $v, ${}, ${1}, ${v), etc. are not accepted as valid and are ignored.
+*/
+
+FindVarRef (s, beg, end, recogEsc)
+char *s;
+int *beg, *end, recogEsc;
+{
+int i;
+char c, delim;
+
+ i = 0;
+ for (;;)
+ {
+ while ((c = s[i]) != '\0')
+ {
+ if (c == '$')
+ {
+ if ((c = s[i+1]) == '{' || c == '(')
+ break;
+ if (recogEsc && c == '$') /* escaped $ */
+ ++i;
+ }
+ ++i;
+ }
+ if (c == '\0')
+ return (0); /* no reference */
+ if (beg != (int *) NULL)
+ *beg = i;
+ if (s[++i] == '{')
+ delim = '}';
+ else
+ delim = ')';
+ ++i;
+ if (!isalpha (s[i])) /* must have at least one char, must */
+ continue; /* begin with letter */
+ while ((c = s[++i]) != '\0')
+ {
+ if (c == delim) /* find matching delim */
+ {
+ if (end != (int *) NULL)
+ *end = i;
+ return (1);
+ }
+ if (!isalnum (c) && c != '_')
+ break;
+ }
+ }
+}
+
+
+FindAllVarRefs (s)
+char *s;
+{
+char name[BUFSIZ];
+int begin, end;
+
+ while (FindVarRef (s, &begin, &end, true))
+ {
+ /* add with empty value if unknown, */
+ /* but don't replace value if known */
+ strncpy (name, s + begin + 2, end - begin - 2);
+ name[end-begin-2] = '\0';
+ AddDef (name, "", 0);
+ s += end + 1;
+ }
+}
+
+
+/*
+ Pull out a variable reference, skipping leading '$(' or '${' and
+ trailing ')' or '}'.
+*/
+
+YankVarRef (dst, src, begin, end)
+char *dst, *src;
+int begin, end;
+{
+ strncpy (dst, src + begin + 2, end - begin - 2);
+ dst[end - begin - 2] = '\0';
+}
+
+
+/*
+ Look for variable references in a variable value and expand them
+ when possible. If a variable is referenced but never defined, it
+ disappears. If a variable is referenced, but its value has not itself
+ been fully expanded, defer expansion of value until another pass, at
+ which time the referenced variable might then be expanded. This
+ prevents infinite expansions on circular references.
+*/
+
+Expand (dp)
+Def *dp;
+{
+Def *dp2;
+/* partain: made 4 * BUFSIZ
+char buf[BUFSIZ];
+*/
+char buf[4 * BUFSIZ];
+int begin, end, vn;
+
+ while (FindVarRef (dp->val, &begin, &end, false))
+ {
+ YankVarRef (buf, dp->val, begin, end);
+ if ((dp2 = FindDefByVar (buf)) == NULL)
+ {
+ fprintf (stderr, "Expand error: can't find %s, ", buf);
+ panic ("quitting");
+ }
+ if (!dp2->simple) /* can't expand, give up for now */
+ break;
+ dp->val[begin] = '\0';
+ sprintf (buf, "%s%s%s", dp->val, dp2->val, &(dp->val)[end+1]);
+ free (dp->val);
+ dp->val = NewString (buf);
+ ++changes;
+ }
+ dp->simple = !FindVarRef (dp->val, NULL, NULL, false);
+}
+
+
+/*
+ Read through file, performing substitutions for any variables
+ known from Makefile. If a variable reference is found that is
+ for an unknown variable, leave it alone, as it may be a reference
+ to a real variable in a shell script.
+*/
+
+DoSub (f)
+FILE *f;
+{
+Def *dp;
+char input[BUFSIZ], var[BUFSIZ], *p;
+int begin, end;
+
+ while (fgets (input, sizeof (input), f) != NULL)
+ {
+ p = input;
+ while (FindVarRef (p, &begin, &end, true))
+ {
+ write (1, p, begin); /* write prefix */
+ YankVarRef (var, p, begin, end);
+ /* if var is known from makefile, write */
+ /* value, else just echo the reference */
+ if ((dp = FindDefByVar (var)) != NULL)
+ write (1, dp->val, strlen (dp->val));
+ else
+ write (1, p + begin, end - begin + 1);
+ p += end + 1;
+ }
+ write (1, p, strlen (p));
+ }
+}
+
+
+/*
+ Get next line from Makefile (combines continuation lines into one).
+ No overflow checking, oops.
+*/
+
+GetLine (f, lbuf)
+FILE *f;
+char *lbuf;
+{
+char buf[BUFSIZ];
+int loop = 1, haveLine = 0, len;
+
+ *lbuf = '\0';
+ while (loop && fgets (buf, sizeof (buf), f) != NULL)
+ {
+ loop = 0;
+ haveLine = 1;
+ len = strlen (buf);
+ if (len > 0 && buf[len-1] == '\n') /* trim newline */
+ buf[--len] = '\0';
+ if (len > 0 && buf[len-1] == '\\') /* need continuation */
+ {
+ loop = 1;
+ buf[--len] = ' ';
+ }
+ strcat (lbuf, buf);
+ }
+ return (haveLine);
+}
+
+
+/*
+ Allocate space for a string, copy the string into it, and return
+ a pointer to the copy.
+*/
+
+
+char *NewString (s)
+char *s;
+{
+char *p;
+
+ if ((p = calloc (1, strlen (s) + 1)) == NULL)
+ panic ("NewString: out of space");
+ return (strcpy (p, s));
+}
+
+
+panic (s)
+char *s;
+{
+ fprintf (stderr, "%s\n", s);
+ exit (1);
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms
new file mode 100644
index 0000000000..7fe019f509
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms
@@ -0,0 +1,128 @@
+.SH
+Theory of Operation
+.LP
+.I msub
+reads the makefile in the current directory (or the file named after the
+.B \-f
+flag) and finds all variable definitions and references.
+Definitions are lines of the form ``\fIname\fR = \fIvalue\fR''.
+References are instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'', either in
+the value part of definition lines, or any part of dependency or command lines.
+Then variable values are examined to eliminate references to other variables
+by replacing the referenced variables with their values.
+Variables which are referenced but never defined have a value of the empty
+string.
+.LP
+Then
+.I msub
+reads any files named on the command line (or
+.I stdin
+if none) and looks for instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'',
+where
+.I var
+is known from the makefile, and substitutes the value of
+.I var .
+.SH
+Purpose
+.LP
+The motivation for
+.I msub
+is that project configuration information is often contained in makefiles
+and it is often desirable to make use of that information.
+.I msub
+allows files to be produced from templates that contain references
+to makefile variables.
+In this sense it is similar to the way that the C preprocessor
+.I cpp
+uses #define statements in header files; the
+makefile is the implicit ``header'' file and definition lines are the
+``#define'' statements.
+.LP
+Although it is possible to use
+.I cpp
+to perform substitutions on templates, a disadvantage of
+.I cpp
+is that it modifies its source in other ways (eg., lines beginning with
+``#'' are special and comments (``/* ... */'') are deleted.
+Also, it is necessary to pass a -D flag for every symbol to be substituted.
+Similarly, for C programs it can be simpler to use
+.I msub
+to produce a single configuration header file from a template
+than to pass a lot of -D flags to each invocation of
+.I cc .
+.LP
+.I msub
+performs no textual modification besides substitution of references
+to makefile variables; it leaves everything else alone.
+In particular,
+references to variables not known from the makefile are left untouched.
+This allows
+.I msub
+to be used to produce shell scripts that use variables of
+their own.
+.LP
+.I msub
+is particularly useful in software projects that use
+.I imake .
+Virtually all configuration information is propagated into makefiles
+thus produced, so it is available for propagation into other files using
+.I msub .
+.SH
+Problems
+.LP
+If
+.I msub
+is used to produce shell scripts, it is unwise for the script to use names
+for its own variables that are the same as those in the makefile.
+The problem can be avoided entirely if, for instance, variables in makefiles
+are all uppercase and the scripts' own variables are lowercase or mixed case.
+.LP
+Circular references in makefile variables are not expanded.
+If a makefile contains the definitions ``X = ${Y}'' and ``Y = ${X}'',
+neither X nor Y will be expanded.
+But that is really a problem with the makefile, not
+.I msub .
+.LP
+.I make
+recognizes
+.B \-f\ \-
+to mean the makefile should be read from
+.I stdin .
+.I msub
+does not.
+.LP
+CC, YACC, etc., have implicit values in
+.I make
+even if not defined in the makefile.
+Not true in
+.I msub .
+.LP
+.I msub
+is more restrictive in the variable names that it recognizes and
+performs substitutions on.
+Names that do not begin with a letter and
+that contain any characters besides letters, digits and underscores are
+ignored.
+This means that variable names such as ``${1}'' are not recognized;
+the reason for this is that shell scripts often use such variables and
+they should be left untouched.
+Also,
+``$\fIx\fR'' is legal in
+.I make
+when
+.I x
+is a single character, but
+.I msub
+ignores such references.
+.i msub
+.LP
+.I make
+allows variables to be defined on the command line.
+.I msub
+does not.
+.LP
+If you try to be tricky with your variable references, e.g., by using
+recursive references, you may get burned.
+.LP
+There is no way to prevent substitution, in a source file, of a reference to
+a variable known from the makefile.
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile
new file mode 100644
index 0000000000..b20a2b7868
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile
@@ -0,0 +1,18 @@
+foo = ${bar}
+bar = ${ugh}
+ugh = Huh?
+space = x
+a = ${wildcard x}
+
+# xyz should be found in next line, given empty value and then the
+# value should be replaced later...
+
+c : ${xyz}
+
+xyz = abc
+
+
+dollar = $$
+doubledollar = ${dollar}${dollar}
+
+
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout
new file mode 100644
index 0000000000..506999f3c1
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout
@@ -0,0 +1,11 @@
+foo = Huh?
+bar = Huh?
+ugh = Huh?
+xy
+${wildcard x}
+
+This (abc) should be abc.
+
+This should be a single dollar: $
+This should be a double dollar: $$
+So should this: $$
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile b/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile
new file mode 100644
index 0000000000..ba3f4ebbf0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile
@@ -0,0 +1,11 @@
+foo = ${foo}
+bar = ${bar}
+ugh = ${ugh}
+${space}y
+${a}
+
+This (${xyz}) should be abc.
+
+This should be a single dollar: ${dollar}
+This should be a double dollar: ${dollar}${dollar}
+So should this: ${doubledollar}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes b/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes
new file mode 100644
index 0000000000..e456aa49e8
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes
@@ -0,0 +1,180 @@
+From mjeffery@reed.edu Sun Nov 29 14:07:23 1992
+From: mjeffery@reed.edu (Mark Jefferys)
+Newsgroups: comp.lang.perl
+Subject: Re: Recursion error in perl 4.035 ?
+Date: 28 Nov 92 23:31:14 GMT
+Organization: Reed College, Portland, OR
+
+In article <1f7uvvINN9tp@roundup.crhc.uiuc.edu> parkes@uiuc.edu writes:
+
+% In cons.c, change the code at or around 1423 from
+%
+% if (willsave)
+% (void)apush(tosave,arg->arg_ptr.arg_str);
+%
+% to
+%
+% if (willsave && arg->arg_ptr.arg_str )
+% (void)apush(tosave,arg->arg_ptr.arg_str);
+
+This is half of my patch to which Larry gave a "Looks OK to me."
+It's been a few months, do I'll post it again.
+
+
+Mark
+
+
+Index: cons.c
+*** Orig/cons.c Thu Jun 11 22:42:01 1992
+--- cons.c Sun Jun 28 18:31:20 1992
+***************
+*** 1353,1359 ****
+
+ /* in any event, save the iterator */
+
+! (void)apush(tosave,cmd->c_short);
+ }
+ shouldsave |= tmpsave;
+ }
+--- 1353,1360 ----
+
+ /* in any event, save the iterator */
+
+! if (cmd->c_short) /* Better safe than sorry */
+! (void)apush(tosave,cmd->c_short);
+ }
+ shouldsave |= tmpsave;
+ }
+***************
+*** 1420,1426 ****
+ shouldsave = TRUE;
+ break;
+ }
+! if (willsave)
+ (void)apush(tosave,arg->arg_ptr.arg_str);
+ return shouldsave;
+ }
+--- 1421,1427 ----
+ shouldsave = TRUE;
+ break;
+ }
+! if (willsave && arg->arg_ptr.arg_str)
+ (void)apush(tosave,arg->arg_ptr.arg_str);
+ return shouldsave;
+ }
+--
+Mark Jefferys Internet: mjeffery@reed.edu
+
+From ezk@cs.columbia.edu Fri Dec 4 19:44:03 1992
+From: ezk@cs.columbia.edu (Erez "HWank1" Zadok)
+Newsgroups: comp.lang.perl
+Subject: REPOST: FIXES to perl/makewhatis (core dump on OW3 man pages)
+Date: 3 Dec 92 12:42:05 GMT
+
+[This is a repost... -Erez]
+
+I've found three small bugs in the the latest version of perl (4.035), which
+I fixed.
+
+The bugs only appeared when I got Tom Christiansen's man package, and ran
+the makewhatis script. Furthermore, it only occurred for one particular set
+of manual pages -- SunOS's OpenWindows 3.
+
+Since it seemed related to DBM, I tried to recompile perl with several
+possible combinations of Sun's /bin/cc, gcc (2.2.2), ndbm, gdbm,
+- -DDEBUGGING, -traditional (for gcc), Perl's malloc, Sun's malloc, etc. to no
+avail. Perl was still dumping core with a segmentation fault. "make test"
+was ok. I was running on various Sun 4 machines, running SunOS 4.1.2.
+
+After debugging I found out that perl was trying to dereference pointers
+that were not initialized.
+
+I fixed this by adding initialization to three declarations in perl.h. The
+ones to rsfp and statstab were needed for non-compressed man pages. When I
+started using compressed man pages I discovered I had to initialize fdpid as
+well. Now everything works fine. Here is the diff file:
+
+*** array.h.orig Tue Nov 24 02:16:30 1992
+--- array.h Mon Nov 23 14:31:16 1992
+***************
+*** 17,22 ****
+--- 17,33 ----
+ *
+ */
+
++ #ifdef NULL
++ #undef NULL
++ #endif
++ #ifndef I286
++ # define NULL 0
++ #else
++ # define NULL 0L
++ #endif
++ #define Null(type) ((type)NULL)
++ #define Nullarray Null(ARRAY*)
++
+ struct atbl {
+ STR **ary_array;
+ STR **ary_alloc;
+*** perl.h.orig Tue Nov 24 02:16:10 1992
+--- perl.h Mon Nov 23 14:30:51 1992
+***************
+*** 868,874 ****
+
+ EXT char *hexdigit INIT("0123456789abcdef0123456789ABCDEFx");
+ EXT char *origfilename;
+! EXT FILE * VOLATILE rsfp;
+ EXT char buf[1024];
+ EXT char *bufptr;
+ EXT char *oldbufptr;
+--- 868,874 ----
+
+ EXT char *hexdigit INIT("0123456789abcdef0123456789ABCDEFx");
+ EXT char *origfilename;
+! EXT FILE * VOLATILE rsfp INIT(Nullfp);
+ EXT char buf[1024];
+ EXT char *bufptr;
+ EXT char *oldbufptr;
+***************
+*** 952,958 ****
+ EXT struct stat statbuf;
+ EXT struct stat statcache;
+ EXT STAB *statstab INIT(Nullstab);
+! EXT STR *statname;
+ #ifndef MSDOS
+ EXT struct tms timesbuf;
+ #endif
+--- 952,958 ----
+ EXT struct stat statbuf;
+ EXT struct stat statcache;
+ EXT STAB *statstab INIT(Nullstab);
+! EXT STR *statname INIT(Nullstr);
+ #ifndef MSDOS
+ EXT struct tms timesbuf;
+ #endif
+***************
+*** 1013,1019 ****
+ EXT ARRAY *lineary; /* lines of script for debugger */
+ EXT ARRAY *dbargs; /* args to call listed by caller function */
+
+! EXT ARRAY *fdpid; /* keep fd-to-pid mappings for mypopen */
+ EXT HASH *pidstatus; /* keep pid-to-status mappings for waitpid */
+
+ EXT int *di; /* for tmp use in debuggers */
+--- 1013,1019 ----
+ EXT ARRAY *lineary; /* lines of script for debugger */
+ EXT ARRAY *dbargs; /* args to call listed by caller function */
+
+! EXT ARRAY *fdpid INIT(Nullarray); /* keep fd-to-pid mappings for mypopen */
+ EXT HASH *pidstatus; /* keep pid-to-status mappings for waitpid */
+
+ EXT int *di; /* for tmp use in debuggers */
+
+
+Erez Zadok.
+Central Research Facilities.
+Columbia University Department of Computer Science.
+- ---
+"A wank's morning starts one jiffy | Arpa: ezk@cs.columbia.edu
+ after midnight." | Usenet: ...!rutgers!columbia!cs!ezk
+ -HebrewWank #1 (US meaning, not UK!) | Bitnet: erzus@cuvmb.BITNET
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile
new file mode 100644
index 0000000000..22d1ccb32f
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile
@@ -0,0 +1,79 @@
+PROGRAMS = lndir \
+ mkdirhier \
+ runstdtest \
+ mkdependC \
+ fastmake \
+ lmake \
+ zap-if-same \
+ moan-if-old \
+ ltx \
+ perltags
+
+all:: $(PROGRAMS)
+/* stuff to have before we get going */
+MsubNeededHere($(PROGRAMS))
+
+/* === BUILD STUFF (installation, etc., below) ========== */
+
+/* std X11 stuff */
+MsubProgramScriptTarget(BourneShell,mkdirhier,mkdirhier.sh,/*no flags*/,/*no dep*/)
+
+BuildPgmFromOneCFile(lndir)
+#if 0
+MsubProgramScriptTarget(BourneShell,lndir,lndir.sh,/*no flags*/,/*no dep*/)
+InstallScriptTarget(lndir, $(INSTSCRIPTDIR))
+#endif
+
+MsubMakefileDependentProgramScriptTarget(PerlCmd,runstdtest,runstdtest.prl,/*no flags*/,/*Makefile*/)
+MsubMakefileDependentProgramScriptTarget(PerlCmd,ltx,ltx.prl,/*no flags*/,/*Makefile*/)
+MsubProgramScriptTarget(PerlCmd,fastmake,fastmake.prl,/*no flags*/,/**/)
+MsubProgramScriptTarget(PerlCmd,zap-if-same,zap-if-same.prl,/*no flags*/,/**/)
+MsubProgramScriptTarget(PerlCmd,moan-if-old,moan-if-old.prl,/*no flags*/,/**/)
+MsubProgramScriptTarget(PerlCmd,perltags,perltags.prl,/*no flags*/,/**/)
+
+MsubProgramScriptTarget(BourneShell,lmake,lmake.sh,/*no flags*/,/*no dep*/)
+
+/*
+mkdependC has to go in "bin" directory, because there may be
+machine-dependent ideas of what CC to use, etc.
+
+ltx, runstdtest: ditto, but only because of TMPDIR
+*/
+MsubMakefileDependentProgramScriptTarget(PerlCmd,mkdependC,mkdependC.prl,/*noflags*/,/*Makefile*/)
+
+#ifdef UseCCMakeDepend
+install::
+ @echo "install makedepend (in ${CURRENT_DIR}) by hand..."
+#endif
+/*
+ lobotomized... install by hand...
+#ifdef UseCCMakeDepend
+InstallProgramTarget(makedepend,$(BINDIR))
+#endif
+*/
+
+/* === INSTALLATION ======== */
+
+/* the rest of these vary from std/useful to hackish dans le extreme */
+
+MakeDirectories(install, $(INSTBINDIR) $(INSTSCRIPTDIR))
+InstallScriptTarget(fastmake, $(INSTSCRIPTDIR))
+InstallScriptTarget(lmake, $(INSTSCRIPTDIR))
+InstallBinaryTarget(lndir, $(INSTBINDIR))
+InstallScriptTarget(ltx, $(INSTBINDIR))
+InstallScriptTarget(mkdependC, $(INSTBINDIR))
+InstallScriptTarget(mkdirhier, $(INSTSCRIPTDIR))
+InstallScriptTarget(perltags, $(INSTSCRIPTDIR))
+InstallScriptTarget(runstdtest, $(INSTBINDIR))
+InstallScriptTarget(zap-if-same, $(INSTSCRIPTDIR))
+InstallScriptTarget(moan-if-old, $(INSTSCRIPTDIR))
+
+InstallManPageTarget(lndir,$(INSTCOMMANDIR),$(COMMANSUFFIX))
+InstallManPageTarget(mkdirhier,$(INSTCOMMANDIR),$(COMMANSUFFIX))
+
+/* === OTHER STUFF ========= */
+
+ExtraStuffToClean($(PROGRAMS))
+
+ClearTagsFile()
+PerlTagsTarget( *.prl ) /* nothing for the Bourne shell scripts */
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl
new file mode 100644
index 0000000000..388b4ed44d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl
@@ -0,0 +1,126 @@
+#! /usr/local/bin/perl
+#
+($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/;
+$Usage = "\n" . <<EOUSAGE;
+Usage:
+ $Pgm [-? or -help] [-k] [-n] [-v] [-t] dir/module-target(s)
+
+This script runs `make' to build the requested target, WITHOUT
+including the dependencies generated by `mkdependHS' (i.e., all those
+derived from import declarations).
+
+With a -t flag, it also sets the modification time of the resulting
+.hi file (one target only, please) to some EARLY date, so that changes
+to that interface will not trigger much useless recompilation.
+
+Typical uses, for module "Bar" in directory "foo":
+
+(1) You've changed "Bar" and you want to recompile it; you know that
+ other module interfaces are stable, so you'd rather do without all
+ of `make''s prognostications:
+
+ $Pgm foo/Bar.s
+
+(2) You've ADDED a new function to "Bar"; you want to recompile that
+ module, BUT NOT TRIGGER LOTS OF FURTHER COMPILATION because of the
+ "changed" interface file:
+
+ $Pgm -t foo/Bar.s
+
+USE AT YOUR OWN RISK: you can make a big mess with this script!
+EOUSAGE
+
+$Makefile = 'Makefile';
+$Tmpfile = "/tmp/Makefile$$";
+chop($Arch = `/bin/arch`);
+$SleazyTouch = '/usr/5bin/touch';
+$DoTouch = 0;
+$Verbose = 0;
+$MakeFlags = '';
+
+sub rm_temp_file {
+ print STDERR "rm $Tmpfile\n" if $Verbose;
+ unlink $Tmpfile;
+ exit(1);
+}
+$SIG{'INT'} = 'rm_temp_file';
+$SIG{'QUIT'} = 'rm_temp_file';
+
+$Target = '';
+$DirMod = ''; # the dir/module-file to make
+
+# process ARGV
+while ($_ = $ARGV[0]) {
+ shift(@ARGV);
+ if (/^-\?$/ || /^-help$/) {
+ print $Usage;
+ exit 1;
+ } elsif (/^-v$/) {
+ $Verbose = 1;
+ } elsif (/^-t$/) {
+ $Do_touch = 1;
+ } elsif (/^-k$/) {
+ $MakeFlags .= ' -k';
+ } elsif (/^-n$/) {
+ $MakeFlags .= ' -n';
+ } elsif (/^-d$/) {
+ $MakeFlags .= ' -d';
+ } elsif (/^-/) {
+ print STDERR "$Pgm: unknown option: $_\n\n$Usage";
+ exit 1;
+ } elsif (/^([A-Z_]+)=(.+)/) {
+ $MakeFlags .= " $1=\"$2\"";
+
+ } elsif ($Do_touch) { # the module file
+ $Target = $_;
+ if ( /([^\/]+\/[^\/\.]+)\.[a-z]+/ ) {
+ $DirMod = $1;
+ } else {
+ print STDERR "$Pgm: argument not of the form: directory/Module.suffix: $_\n\n$Usage";
+ exit 1;
+ }
+ } else { # accumulate as "Target"...
+ $Target .= " $_";
+ }
+}
+
+if ($Do_touch && $Target =~ / /) {
+ print STDERR "$Pgm: too many arguments\n\n$Usage";
+ exit 1;
+}
+
+open(INF, "<$Makefile") || die "Can't open $Makefile for input\n";
+
+open(OUTF,">$Tmpfile") || die "Can't open $Tmpfile for output\n";
+select(OUTF);
+
+$_ = <INF>;
+
+# copy through until ...
+while ( $_ && ! /^# DO NOT DELETE: Beginning of Haskell dependencies/ ) {
+ print $_;
+ $_ = <INF>;
+}
+
+# now copy through 'til the end, omittin the %.[so] : %.hi dependencies
+while ( $_ ) {
+ print $_ if ! /^\S+ : \S+\.hi$/;
+ $_ = <INF>;
+}
+
+close(INF);
+close(OUTF);
+
+if ($Arch ne "sun3") {
+ $Make = 'make JMAKE=jmake LIT2PGM=lit2pgm LIT2LATEX=lit2latex LIT2TEXI=lit2texi MKDEPENDLIT=mkdependlit MAKEINFO=makeinfo POSTMAKEINFO=postmakeinfo';
+} else {
+ $Make = 'make';
+}
+print STDERR "$Make $MakeFlags -f $Tmpfile $Target; rm $Tmpfile\n" if $Verbose;
+
+system( "$Make $MakeFlags -f $Tmpfile $Target; rm $Tmpfile" );
+
+if ($Do_touch) {
+ print STDERR "$SleazyTouch -m 01010101 $DirMod\.hi\n" if $Verbose;
+ system( "$SleazyTouch -m 01010101 $DirMod\.hi" );
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh
new file mode 100644
index 0000000000..133405cb07
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh
@@ -0,0 +1,2 @@
+#! /bin/sh
+make JMAKE=jmake LIT2PGM=lit2pgm LIT2LATEX=lit2latex LIT2TEXI=lit2texi MKDEPENDLIT=mkdependlit MAKEINFO=makeinfo POSTMAKEINFO=postmakeinfo $*
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c
new file mode 100644
index 0000000000..d365de6755
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c
@@ -0,0 +1,217 @@
+/* $XConsortium: lndir.c,v 1.5 91/07/21 15:52:11 rws Exp $ */
+/* Create shadow link tree (after X11R4 script of the same name)
+ Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
+
+/* Copyright 1990, Massachusetts Institute of Technology
+
+ Permission to use, copy, modify, and distribute this program for any purpose
+ and without fee is hereby granted, provided that this copyright and
+ permission notice appear on all copies and supporting documentation, that
+ the name of MIT not be used in advertising or publicity pertaining to
+ distribution of this program without specific prior permission, and that
+ notice be given in supporting documentation that copying and distribution is
+ by permission of MIT. MIT makes no representations about the suitability of
+ this software for any purpose. It is provided "as is" without expressed or
+ implied warranty.
+*/
+
+/* From the original /bin/sh script:
+
+ Used to create a copy of the a directory tree that has links for all
+ non-directories (except those named RCS or SCCS). If you are
+ building the distribution on more than one machine, you should use
+ this script.
+
+ If your master sources are located in /usr/local/src/X and you would like
+ your link tree to be in /usr/local/src/new-X, do the following:
+
+ % mkdir /usr/local/src/new-X
+ % cd /usr/local/src/new-X
+ % lndir ../X
+*/
+
+/*#include <X11/Xos.h> */
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+
+#ifndef X_NOT_POSIX
+#include <dirent.h>
+#else
+#ifdef SYSV
+#include <dirent.h>
+#else
+#ifdef USG
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#ifndef dirent
+#define dirent direct
+#endif
+#endif
+#endif
+#endif
+
+extern int errno;
+int silent;
+
+void
+quit (code, fmt, a1, a2, a3)
+char *fmt;
+{
+ fprintf (stderr, fmt, a1, a2, a3);
+ putc ('\n', stderr);
+ exit (code);
+}
+
+void
+quiterr (code, s)
+char *s;
+{
+ perror (s);
+ exit (code);
+}
+
+void
+msg (fmt, a1, a2, a3)
+char *fmt;
+{
+ fprintf (stderr, fmt, a1, a2, a3);
+ putc ('\n', stderr);
+}
+
+
+/* Recursively create symbolic links from the current directory to the "from"
+ directory. Assumes that files described by fs and ts are directories. */
+
+dodir (fn, fs, ts, rel)
+char *fn; /* name of "from" directory, either absolute or
+ relative to cwd */
+struct stat *fs, *ts; /* stats for the "from" directory and cwd */
+int rel; /* if true, prepend "../" to fn before using */
+{
+ DIR *df;
+ struct dirent *dp;
+ char buf[MAXPATHLEN + 1], *p;
+ char symbuf[MAXPATHLEN + 1];
+ struct stat sb, sc;
+ int n_dirs;
+
+ if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
+ msg ("%s: From and to directories are identical!", fn);
+ return 1;
+ }
+
+ if (rel)
+ strcpy (buf, "../");
+ else
+ buf[0] = '\0';
+ strcat (buf, fn);
+
+ if (!(df = opendir (buf))) {
+ msg ("%s: Cannot opendir", buf);
+ return 1;
+ }
+
+ p = buf + strlen (buf);
+ *p++ = '/';
+ n_dirs = fs->st_nlink;
+ while (dp = readdir (df)) {
+ strcpy (p, dp->d_name);
+
+ if (n_dirs > 0) {
+ if (stat (buf, &sb) < 0) {
+ perror (buf);
+ continue;
+ }
+
+ if (sb.st_mode & S_IFDIR) {
+ /* directory */
+ n_dirs--;
+ if (dp->d_name[0] == '.' &&
+ (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
+ dp->d_name[2] == '\0')))
+ continue;
+ if (!strcmp (dp->d_name, "RCS"))
+ continue;
+ if (!strcmp (dp->d_name, "SCCS"))
+ continue;
+ if (!silent)
+ printf ("%s:\n", buf);
+ if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
+ if (mkdir (dp->d_name, 0777) < 0 ||
+ stat (dp->d_name, &sc) < 0) {
+ perror (dp->d_name);
+ continue;
+ }
+ }
+ if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
+ msg ("%s: is a link instead of a directory\n", dp->d_name);
+ continue;
+ }
+ if (chdir (dp->d_name) < 0) {
+ perror (dp->d_name);
+ continue;
+ }
+ dodir (buf, &sb, &sc, (buf[0] != '/'));
+ if (chdir ("..") < 0)
+ quiterr (1, "..");
+ continue;
+ }
+ }
+
+ /* non-directory */
+ if (symlink (buf, dp->d_name) < 0) {
+ int saverrno = errno;
+ int symlen;
+ symlen = readlink(dp->d_name, symbuf, sizeof(symbuf) - 1);
+ errno = saverrno;
+ if (symlen > 0)
+ symbuf[symlen] = '\0';
+ if (symlen < 0 || strcmp(symbuf, buf))
+ perror (dp->d_name);
+ }
+ }
+
+ closedir (df);
+ return 0;
+}
+
+
+main (ac, av)
+int ac;
+char **av;
+{
+ char *fn, *tn;
+ struct stat fs, ts;
+
+ silent = 0;
+ if (ac > 1 && !strcmp(av[1], "-silent")) {
+ silent = 1;
+ }
+ if (ac < silent + 2 || ac > silent + 3)
+ quit (1, "usage: %s [-silent] fromdir [todir]", av[0]);
+
+ fn = av[silent + 1];
+ if (ac == silent + 3)
+ tn = av[silent + 2];
+ else
+ tn = ".";
+
+ /* to directory */
+ if (stat (tn, &ts) < 0)
+ quiterr (1, tn);
+ if (!(ts.st_mode & S_IFDIR))
+ quit (2, "%s: Not a directory", tn);
+ if (chdir (tn) < 0)
+ quiterr (1, tn);
+
+ /* from directory */
+ if (stat (fn, &fs) < 0)
+ quiterr (1, fn);
+ if (!(fs.st_mode & S_IFDIR))
+ quit (2, "%s: Not a directory", fn);
+
+ exit (dodir (fn, &fs, &ts, 0));
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man
new file mode 100644
index 0000000000..ae5b4285bd
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man
@@ -0,0 +1,61 @@
+.TH LNDIR 1 "Release 5" "X Version 11"
+.SH NAME
+lndir \- create a shadow directory of symbolic links to another directory tree
+.SH SYNOPSIS
+.B lndir
+fromdir [todir]
+.SH DESCRIPTION
+.I Lndir
+makes a shadow copy
+.I todir
+of a directory tree
+.I fromdir,
+except that the shadow is not
+populated with real files but instead with symbolic links pointing at
+the real files in the
+.I fromdir
+directory tree. This is usually useful for maintaining source code for
+different machine architectures. You create a shadow directory
+containing links to the real source which you will have usually NFS
+mounted from a machine of a different architecture, and then recompile
+it. The object files will be in the shadow directory, while the
+source files in the shadow directory are just symlinks to the real
+files.
+.PP
+This has the advantage that if you update the source, you need not
+propagate the change to the other architectures by hand, since all
+source in shadow directories are symlinks to the real thing: just cd
+to the shadow directory and recompile away.
+.PP
+The
+.I todir
+argument is optional and defaults to the current directory. The
+.I fromdir
+argument may be relative (e.g., ../src) and is relative to
+.I todir
+(not the current directory).
+.PP
+.ft B
+Note that RCS and SCCS directories are not shadowed.
+.ft
+.PP
+Note that if you add files, you must run
+.I lndir
+again. Deleting files is a more painful problem; the symlinks will
+just point into never never land.
+.SH BUGS
+.I Patch
+gets upset if it cannot change the files. You should never run
+.I patch
+from a shadow directory anyway.
+.PP
+You need to use something like
+.nf
+ find todir -type l -print | xargs rm
+.fi
+to clear out all files before you can relink (if fromdir moved, for instance).
+Something like
+.nf
+ find . \\! -type d -print
+.fi
+will find all files that are not directories.
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh
new file mode 100644
index 0000000000..f09bf7f590
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh
@@ -0,0 +1,85 @@
+#! /bin/sh
+
+# lndir - create shadow link tree
+#
+# $XConsortium: lndir.sh,v 1.8 91/04/15 17:55:03 rws Exp $
+#
+# Used to create a copy of the a directory tree that has links for all
+# non- directories (except those named RCS or SCCS). If you are
+# building the distribution on more than one machine, you should use
+# this script.
+#
+# If your master sources are located in /usr/local/src/X and you would like
+# your link tree to be in /usr/local/src/new-X, do the following:
+#
+# % mkdir /usr/local/src/new-X
+# % cd /usr/local/src/new-X
+# % lndir ../X
+
+USAGE="Usage: $0 fromdir [todir]"
+
+if [ $# -lt 1 -o $# -gt 2 ]
+then
+ echo "$USAGE"
+ exit 1
+fi
+
+DIRFROM=$1
+
+if [ $# -eq 2 ];
+then
+ DIRTO=$2
+else
+ DIRTO=.
+fi
+
+if [ ! -d $DIRTO ]
+then
+ echo "$0: $DIRTO is not a directory"
+ echo "$USAGE"
+ exit 2
+fi
+
+cd $DIRTO
+
+if [ ! -d $DIRFROM ]
+then
+ echo "$0: $DIRFROM is not a directory"
+ echo "$USAGE"
+ exit 2
+fi
+
+pwd=`pwd`
+
+if [ `(cd $DIRFROM; pwd)` = $pwd ]
+then
+ echo "$pwd: FROM and TO are identical!"
+ exit 1
+fi
+
+for file in `ls -af $DIRFROM`
+do
+ if [ ! -d $DIRFROM/$file ]
+ then
+ ln -s $DIRFROM/$file .
+ else
+ if [ $file != RCS -a $file != SCCS -a $file != . -a $file != .. ]
+ then
+ echo $file:
+ mkdir $file
+ (cd $file
+ pwd=`pwd`
+ case "$DIRFROM" in
+ /*) ;;
+ *) DIRFROM=../$DIRFROM ;;
+ esac
+ if [ `(cd $DIRFROM/$file; pwd)` = $pwd ]
+ then
+ echo "$pwd: FROM and TO are identical!"
+ exit 1
+ fi
+ $0 $DIRFROM/$file
+ )
+ fi
+ fi
+done
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl
new file mode 100644
index 0000000000..1bce758270
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl
@@ -0,0 +1,215 @@
+$Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/;
+#
+# set up signal handler
+sub quit_upon_signal { &rm_temp_files_and_exit(); }
+$SIG{'INT'} = 'quit_upon_signal';
+$SIG{'QUIT'} = 'quit_upon_signal';
+#
+$Verbose = 0;
+if ($ARGV[0] eq '-v') {
+ $Verbose = 1;
+ shift(@ARGV);
+}
+#
+die "$Pgm: must have exactly one argument\n" if $#ARGV != 0;
+# figure out input file and its filename root
+if (-f $ARGV[0]) {
+ $TeX_input = $ARGV[0];
+ if ($TeX_input =~ /(.+)\.[^\.\/\n]+$/) {
+ $TeX_root = $1;
+ } else {
+ $TeX_root = $TeX_input;
+ }
+} elsif (-f $ARGV[0].'.tex') {
+ $TeX_input = $ARGV[0].'.tex';
+ $TeX_root = $ARGV[0];
+} else {
+ die "$Pgm: input file $ARGV[0] doesn't exist\n";
+}
+
+sub rm_temp_files {
+ system("rm -f $(TMPDIR)/ltx-*.$$");
+}
+sub rm_temp_files_and_exit {
+ system("rm -f $(TMPDIR)/ltx-*.$$");
+ exit(1);
+}
+$SIG{'INT'} = 'rm_temp_files_and_exit';
+$SIG{'QUIT'} = 'rm_temp_files_and_exit';
+
+sub die_gracefully {
+ local($msg) = @_;
+
+ print STDERR $msg;
+ &rm_temp_files_and_exit();
+}
+
+# must read through root file to see if a \bibliography
+# is there...
+$Bibliography_requested = 0;
+open(TEXIF, "<$TeX_input")
+ || &die_gracefully("$Pgm: Can't read $TeX_input\n");
+while (<TEXIF>) {
+ $Bibliography_requested = 1 if /^\\bibliography/;
+}
+close(TEXIF);
+&die_gracefully("$Pgm: reading $TeX_input had errors\n") if $? >> 8;
+
+# run latex first time (?)
+&run_latex(); # sets $Says_labels_changed
+$Times_run = 1;
+
+while (&something_more_needed()) {
+
+ print STDERR "labels_changed=$Says_label_changed;bibtex_needed=$BibTeX_run_needed;makeindex_needed=$MakeIndex_run_needed\n" if $Verbose;
+
+ if ($BibTeX_run_needed) {
+ &run_bibtex();
+ }
+ if ($MakeIndex_run_needed) {
+ unlink "$TeX_root.ind";
+ (system("makeindex $TeX_root.idx") >> 8)
+ && &die_gracefully("$Pgm: makeindex $TeX_root.idx had errors\n");
+ }
+
+ # save (copy) .aux file as .aux-prev file for future ref
+ # ditto for .idx file
+ unlink "$TeX_root.aux-prev";
+ (system("cp $TeX_root.aux $TeX_root.aux-prev") >> 8)
+ && &die_gracefully("$Pgm: cp $TeX_root.aux $TeX_root.aux-prev failed\n");
+ if (-f "$TeX_root.idx") {
+ unlink "$TeX_root.idx-prev";
+ (system("cp $TeX_root.idx $TeX_root.idx-prev") >> 8)
+ && &die_gracefully("$Pgm: cp $TeX_root.idx $TeX_root.idx-prev failed\n");
+ }
+
+ # run latex again
+ &run_latex(); # sets $Says_labels_changed
+ $Times_run++;
+
+ if ($Times_run >= 4) {
+ print STDERR "*** I don't run LaTeX more than four times;\n";
+ print STDERR "*** Something is probably wrong...\n";
+ &rm_temp_files_and_exit();
+ }
+}
+&rm_temp_files();
+exit(0);
+
+sub run_latex {
+ $Says_labels_changed = 0;
+ $Multiply_defined_labels = 0;
+
+ select(STDERR); $| = 1; select(STDOUT); # no buffering on STDERR
+ print STDERR "$Pgm: *** running LaTeX...\n" if $Verbose;
+ unlink "$TeX_root.dvi";
+
+ open(LTXPIPE, "latex $TeX_input 2>&1 |")
+ || &die_gracefully("$Pgm: Can't run latex pipe\n");
+ while (<LTXPIPE>) {
+ $Multiply_defined_labels = 1 if /^LaTeX Warning: Label .* multiply defined/;
+ $Says_labels_changed = 1 if /^LaTeX Warning: Label\(s\) may have changed/
+ && ! $Multiply_defined_labels;
+ print STDERR $_;
+ }
+ close(LTXPIPE);
+ &die_gracefully("$Pgm: LaTeX run had errors\n") if $? >> 8;
+
+ # sort .idx file, because this helps makeindex
+ # (can you say `bug'?)
+ if (-f "$TeX_root.idx") {
+ print STDERR "$Pgm: *** sorting $TeX_root.idx...\n" if $Verbose;
+ (system("sort $TeX_root.idx -o $TeX_root.idx") >> 8)
+ && &die_gracefully("$Pgm: sorting $TeX_root.idx failed\n");
+ }
+
+}
+
+sub run_bibtex { # ugly because bibtex doesn't return a correct error status
+ local($bibtex_had_errors) = 0;
+
+ print STDERR "$Pgm: *** running BibTeX...\n" if $Verbose;
+ unlink "$TeX_root.bbl";
+
+ $| = 1; # no buffering
+ open(BIBTXPIPE, "bibtex $TeX_root 2>&1 |")
+ || &die_gracefully("$Pgm: Can't run bibtex pipe\n");
+ while (<BIBTXPIPE>) {
+ $bibtex_had_errors = 1 if /^\(There.*error message(s)?\)$/;
+ print STDERR $_;
+ }
+ close(BIBTXPIPE);
+ &die_gracefully("$Pgm: BibTeX run had errors\n")
+ if $? >> 8 || $bibtex_had_errors;
+}
+
+sub something_more_needed {
+ # returns 1 or 0 if we need to run LaTeX
+ # possibly preceded by bibtex and/or makeindex run
+
+ # $Says_labels_changed was set by previous &run_latex...
+ $BibTeX_run_needed = 0;
+ $MakeIndex_run_needed = 0;
+
+ if ( ! -f ($TeX_root . '.aux-prev')) { # this was the first run
+
+ print STDERR "$Pgm: *** 'twas first run of LaTeX on $TeX_input\n" if $Verbose;
+
+ # we need makeindex to run if a non-zero-sized .idx file exists
+ #
+ $MakeIndex_run_needed = 1
+ if -f "$TeX_root.idx" && -s "$TeX_root.idx";
+
+ # we need bibtex to run if there are \citations in the .aux file
+ #
+ &slurp_aux_file('aux');
+ $BibTeX_run_needed = 1
+ if $Bibliography_requested &&
+ -f "$(TMPDIR)/ltx-aux-cite.$$" &&
+ -s "$(TMPDIR)/ltx-aux-cite.$$";
+
+
+ } else { # ltx had been run before (.aux-prev/.idx-prev files exist)
+
+ # slurp both .aux and .aux-prev files
+ &slurp_aux_file('aux');
+ &slurp_aux_file('aux-prev');
+
+ local($tmp_pre) = "$(TMPDIR)/ltx";
+
+ if ((-s "$tmp_pre-.aux-cite.$$") # there are still \cite's in there
+ && (system("cmp -s $tmp_pre-.aux-cite.$$ $tmp_pre-.aux-prev-cite.$$") >> 8)) {
+ $BibTeX_run_needed = 1 if $Bibliography_requested;
+ if ($Verbose) {
+ system("diff -c1 $tmp_pre-.aux-prev-cite.$$ $tmp_pre-.aux-cite.$$");
+ }
+ }
+
+ if (-f "$TeX_root.idx") {
+ $MakeIndex_run_needed =
+ (system("cmp -s $TeX_root.idx $TeX_root.idx-prev") >> 8) ? 1 : 0;
+ if ($MakeIndex_run_needed && $Verbose) {
+ system("diff -c1 $TeX_root.idx-prev $TeX_root.idx");
+ }
+ }
+ }
+
+ $Says_labels_changed || $BibTeX_run_needed || $MakeIndex_run_needed;
+}
+
+sub slurp_aux_file {
+ local($ext) = @_;
+
+ # copy all citations from slurpfile into $(TMPDIR)/ltx-$ext-cite.$$
+
+ open(SLURPF,"< $TeX_root.$ext")
+ || &die_gracefully("$Pgm: Can't open $TeX_root.$ext for reading\n");
+ open(CITEF,"> $(TMPDIR)/ltx-$ext-cite.$$")
+ || &die_gracefully("$Pgm: Can't open $(TMPDIR)/ltx-$ext-cite.$$ for writing\n");
+
+ while (<SLURPF>) {
+ print CITEF $_ if /\\citation/;
+ }
+ close(CITEF);
+ close(SLURPF);
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl
new file mode 100644
index 0000000000..f352f64e48
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl
@@ -0,0 +1,502 @@
+#!/usr/local/bin/perl -- # -*-Perl-*-
+##############################################################################
+#
+# m5 is a poor-man's m4
+#
+# written in March of 1991 by Bill Mann; tested with v3.044 of perl
+# bill@ksr.com (ksr!bill@uunet.uu.net)
+#
+# This program may be used or modified for any purpose, but I would
+# appreciate it if you would reports bugs and fixes to me, and credit
+# yourself with any modifications you make. -bill
+#
+# I have mailed Larry Wall a fix for the 'perl bug' mentioned in the
+# comments below. Once this bug is fixed, removing the 'redundant'
+# double-quotes will provide some improvement in speed; the speed-up
+# will be application dependent. -bill
+#
+##############################################################################
+
+#-- where I got it -----------------------------------------------------------
+#From: Adrian F Clark <alien@sx.ac.uk>
+#To: partain
+#Subject: Re: Macro-processor in Perl?
+#Date: Thu, 25 Jul 91 09:43:05 BST
+#
+#"Ask and ye shall receive" ... this sounds like just what we both
+#want!
+#
+#..a
+#
+#Date: Wed, 24 Jul 91 18:09:30 EDT
+#From: bill%ksr.com@uk.ac.essex.mailhost
+#To: "Adrian F Clark" <alien%sx.ac.uk@uk.ac.essex.mailhost>
+#In-Reply-To: alien@essex.ac.uk's message of 24 Jul 91 09:32:13 EDT
+#Subject: Re: Macro-processor in Perl?
+#Sender: bill%ksr.com%ksr%uunet.uu.net@uk.ac.essex.mailhost
+#
+#I wrote a m4 clone, with just a couple of features missing, and a
+#couple added, because the versions of m4 we had in-house, mostly from
+#SUN, were either very old or buggy.
+#
+#The major missing feature is multiple separate output files. The
+#major addition is that eval() now does a full-fledged perl eval, which
+#'just happens' to include everything the m4 eval includes, in the same
+#syntax.
+#
+#This program is in daily use, and has been tested by the author, but
+#it is only used for a few applications, so problems may still be
+#lurking. I'll be happy to answer a few questions, but can't promise
+#to spend too much time, and I provide no guarantees. I call it m5
+#just keep it distinct from m4.
+#-----------------------------------------------------------------------------
+
+# Auto identification
+#$program_path = $0;
+#$program_name = $program_path;
+#$program_name =~ s:^.*/::;
+#$cmd_line = join(' ', $program_name, @ARGV);
+#$rcs_id = '$Id: m5,v 1.1 1991/03/12 19:48:13 bill Exp $ ';
+select (STDERR); $| = 1; select (STDOUT);
+#print STDERR "$program_path ", '$Revision: 1.1 $ ', "\n";
+#print STDERR $rcs_id, "\n";
+
+
+#eval "print STDERR \$die='Unknown parameter $1\n' if !defined \$$1; \$$1=\$';"
+# while ($ARGV[0] =~ /^(\w+)=/ && shift(@ARGV));
+#exit 255 if $die; # process any FOO=bar switches
+
+%D = ("changecom", "\000changecom",
+ "changequote", "\000changequote",
+ "decr", "\000decr",
+ "define", "\000define",
+ "defn", "\000defn",
+ "dnl", "\000dnl",
+ "dumpdef", "\000dumpdef",
+ "errprint", "\000errprint",
+ "eval", "\000eval",
+ "ifdef", "\000ifdef",
+ "ifelse", "\000ifelse",
+ "include", "\000include",
+ "incr", "\000incr",
+ "index", "\000index",
+ "len", "\000len",
+ "maketemp", "\000maketemp",
+ "m4exit", "\000m4exit",
+ "m4wrap", "\000m4wrap",
+ "popdef", "\000popdef",
+ "pushdef", "\000pushdef",
+ "repeat", "\000repeat",
+ "shift", "\000shift",
+ "substr", "\000substr",
+ "syscmd", "\000syscmd",
+ "undefine", "\000undefine",
+ "unix", "",
+ );
+
+$ccp = 0; $file = '';
+@inc = '';
+while ($ARGV[0] =~ /^-./) {
+ $_ = shift(@ARGV);
+ /^-D(\w+)(=(.*))?$/ && ($D{$1} = (defined($3)? $3 : ''), next);
+ /^-U(\w+)$/ && (delete $D{$1}, next);
+ /^-e$/ && (next); # not implemented yet -bill
+ /^-s$/ && ($ccp = 1, next);
+ /^-I(.*)$/ && (push(@inc, ($1 || shift(@ARGV)) . '/'), next);
+ die "unrecognized switch: $_\n";
+}
+
+# other globals: @args, $ab, $mi, $lq, $rq, $skip
+$ab = $mi = 0; # undef would be ok
+$m4wrap = '';
+
+$lcom = "\#";
+$rcom = "\n";
+&changequote;
+
+@ARGV || unshift(@ARGV, '-');
+
+for (shift(@ARGV)) { # 'feature': each file must end cleanly
+ print &expand('', &openf($_));
+}
+$m4wrap ne '' && print &expand($m4wrap, '');
+exit;
+
+sub openf {
+ $ARGV = $_[0];
+ $FH = "F" . @FH;
+ open($FH, $ARGV) || die "Can't open '$ARGV': $@";
+ $line = 0;
+ $ccp && printf ("#line %s \"%s\"\n", 1, $ARGV);
+ $FH;
+}
+
+# $st states:
+# 0: normal text, or reading macro arguments if $pf != 0
+# 1: quoted string
+# 2: comment
+# 3: starting to read an argument (skipping white space)
+
+# expand expands its input string, removing one layer of matching quotes;
+# it expands defined symbols as long as they are not between quotes.
+# whenever it reaches the end of the string it reads a new line and extends
+# its input if possible; if it can't it returns errors if in a macro
+# argument or in a quoted string.
+sub expand {
+ local($in,$FH) = @_;
+ local($i,$st,$qn,$pn) = (0,0,0,0); # used recursively
+ local($ci,$pi,$t); # not used recursively, but declared anyway
+
+ while (1) { # for 'each' character
+ if ($i == length($in)) {
+ if ($FH) {
+ unless ($pn) { # defer output while reading macro arguments
+ print $in;
+ $in = '';
+ $i = $ci = 0;
+ }
+
+ if ($t = <$FH>) {
+ $in .= $t;
+ $line++;
+ next; # process next line
+ }
+
+ close($FH);
+
+ if (@argv) {
+ $FH = pop(@FH);
+ $ARGV = pop(@argv);
+ $line = pop(@line);
+ $in .= pop(@in);
+ $ccp && printf ("#line %s \"%s\"\n", $line, $ARGV);
+ next;
+ }
+ }
+ $st == 1 && die "missing close quote\n";
+ $st == 2 && die "missing close comment\n";
+ $pn && die "missing close parenthesis\n";
+ last;
+ }
+
+## substr($in, $i) =~ $skip && ($i += length($&)) == length($in) && next;
+ substr($in, $i) =~ /^[ \t0-9]+/ &&
+ ($i += length($&)) == length($in) && next;
+
+ if ($st == 1) { # if in a quoted string
+ if (substr($in, $i, length($rq)) eq $rq) {
+ if (--$qn) {
+ $i += length($rq);
+ } else {
+ substr($in, $i, length($rq)) = '';
+ $st = 0;
+ }
+ next;
+ }
+ if (substr($in, $i, length($lq)) eq $lq) {
+ ++$qn;
+ $i += length($lq);
+ next;
+ }
+ ++$i;
+ next;
+ }
+ elsif ($st == 2) { # if in a comment
+ if (($i = index($in, $rcom, $i)) == -1) { # extends past eol
+ $i = length($in);
+ next;
+ }
+
+ $i += length($rcom);
+ if ($pn) { # if in parens
+ substr($in, $ci, $i-$ci) = '';
+ $i = $ci;
+ $rcom eq "\n" && (substr($in, $i++, 0) = "\n");
+ }
+ $st = 0;
+ next;
+ }
+ elsif ($st == 3) { # if starting an argument
+ substr($in, $pi, $i-$pi+1) =~ s/^(\s*)(\S)/$2/ &&
+ ($i -= length($1), $st = 0);
+ }
+
+ if (substr($in, $i, length($lq)) eq $lq && $lq) {
+ substr($in, $i, length($lq)) = '';
+ $st = $qn = 1;
+ next;
+ }
+
+ if (substr($in, $i, length($lcom)) eq $lcom && $lcom) {
+ $i += length($lcom);
+ $ci = $i;
+ $st = 2;
+ next;
+ }
+
+ if ($pn) {
+ $t = substr($in, $i, 1);
+ if ($t eq '(') {
+ ++$pn;
+ ++$i;
+ next;
+ }
+ elsif ($t eq ',') {
+ if ($pn == 1) {
+ push(@args, substr($in, $pi, $i-$pi));
+ $pi = $i+1;
+ $st = 3;
+ }
+ ++$i;
+ next;
+ }
+ elsif ($t eq ')') {
+ if (--$pn == 0) {
+ push(@args, substr($in, $pi, $i-$pi));
+ ++$i;
+ &callm;
+ $pi = pop(@pi);
+ $pn = pop(@pn);
+ next;
+ }
+ ++$i;
+ next;
+ }
+ }
+
+ substr($in, $i) =~ /^([a-z_]\w*)(\()?/i || (++$i, next);
+ defined($D{$1}) || ($i += length($1), next);
+
+ push(@ab, $ab);
+ push(@args, $1);
+ $ab = $#args;
+ push(@mi, $mi);
+ $mi = $i;
+ $i += length($&);
+
+ if ($2) {
+ push(@pi, $pi);
+ push(@pn, $pn);
+ $pi = $i;
+ $pn = 1;
+ $st = 3;
+ next;
+ }
+
+ &callm;
+ }
+ $in;
+}
+
+sub callm {
+
+ if (($t = $D{$args[$ab]}) =~ s/^\000//) {
+ $t = &$t; # may recurse here
+ } else {
+ $t =~ s/\$(\#|\*|\@|\d)/$1 eq '#' ? $#args-$ab :
+ $1 eq '*' ? join(',', @args[$ab+1..$#args]) :
+ $1 eq '@' ? join(',', &quotelist(@args[$ab+1..$#args])) :
+ $args[$ab+$1]/ge;
+ }
+
+ $ccp &&
+ (substr($in, $mi, $i-$mi) =~ tr/\n/\n/) != ($t =~ tr/\n/\n/) &&
+ ($t =~ s/\n$//,
+ $t .= sprintf("\n#line %s \"%s\"\n", $line, $ARGV));
+ substr($in, $mi, $i-$mi) = $t;
+
+ $i = $mi; # rescan
+ $#args = $ab-1;
+ $mi = pop(@mi);
+ $ab = pop(@ab);
+}
+
+sub quotelist {
+ local(@T);
+ for (@_) {
+ push(@T, $lq . $_ . $rq);
+ }
+ @T;
+}
+
+sub setskip {
+ ($skip = "$lcom$rcom$lq$rq(,)") =~ s/(\W)/\\$1/g;
+ $skip = "^[^a-zA-Z_$skip]+";
+}
+
+# m5 functions:
+
+sub changecom {
+ $lcom = $args[$ab+1];
+ $rcom = $args[$ab+2] || "\n";
+ &setskip;
+ "";
+}
+
+sub changequote {
+ $lq = $args[$ab+1];
+ $rq = $args[$ab+2] || $lq;
+ if ($#args <= $ab) { # if no arguments at all
+ $lq = "\`";
+ $rq = "\'";
+ }
+ &setskip;
+ "";
+}
+
+sub decr {
+ $t = $args[$ab+1] - 1;
+ "$t"; # quotes required for perl bug
+}
+
+sub define {
+ $args[$ab+1] =~ /^[a-z_]\w*$/i || die "bad macro name: '$args[$ab+1]'\n";
+ $D{$args[$ab+1]} = $args[$ab+2];
+ "";
+}
+
+sub defn {
+ $t = '';
+ for (@args[$ab+1..$#args]) {
+ $t .= $lq . $D{$_} . $rq;
+ }
+ $t;
+}
+
+sub dnl {
+ substr($in, $i) =~ s/[^\n]*\n?//;
+ "";
+}
+
+sub dumpdef {
+ for (sort(keys %D)) {
+ if (($t = $D{$_}) =~ s/^\000//) {
+ printf STDERR ("%s:\t<%s>\n", $_, $t);
+ } else {
+ printf STDERR ("%s:\t%s%s%s\n", $_, $lq, $t, $rq);
+ }
+ }
+ "";
+}
+
+sub errprint {
+ print STDERR $args[$ab+1], "\n";
+ "";
+}
+
+sub eval {
+ local($r) = int($args[$ab+2]);
+ package m5;
+ $main't = eval $main'args[$main'ab+1]; #'];
+ package main;
+ $@ && die "eval($args[$ab+1]) failed: $@\n";
+ if ($r > 1 && $t =~ s/^(-)?(\d+)$//) { # if a radix is specified
+ local($d) = $2;
+ do {
+ $t = ('0'..'9','A'..'Z')[$d % $r] . $t;
+ $d = int($d / $r);
+ } while $d;
+
+ $d = $args[$ab+3] - length($t);
+ $d > 0 && ($t = ('0' x $d) . $t);
+ $t = $1 . $t;
+ }
+ "$t"; # quotes required for perl bug
+}
+
+sub ifdef {
+ defined($D{$args[$ab+1]}) ? $args[$ab+2] : $args[$ab+3];
+}
+
+sub ifelse {
+ for ($t = $ab+1; $t < $#args; $t += 3) {
+ $args[$t] eq $args[$t+1] && return "$args[$t+2]";
+ }
+ return "$args[$t]"; # quotes required for perl bug
+}
+
+sub include {
+ for (@inc) { # search -I list
+ $t = "$_$args[$ab+1]";
+ if (-f $t) {
+ push(@FH, $FH);
+ push(@argv, $ARGV);
+ push(@line, $line);
+ push(@in, substr($in, $i));
+ substr($in, $i) = '';
+ &openf($t);
+ return "";
+ }
+ }
+ die "Can't find include file $args[$ab+1]";
+}
+
+sub incr {
+ $t = $args[$ab+1] + 1;
+ "$t"; # quotes required for perl bug
+}
+
+sub index {
+ $t = index($args[$ab+1], $args[$ab+2]);
+ "$t"; # quotes required for perl bug
+}
+
+sub len {
+ $t = length($args[$ab+1]);
+ "$t"; # quotes required for perl bug
+}
+
+sub maketemp {
+ ($t = $args[$ab+1]) =~ s/X{1,6}$/a$$/; # via experiments
+ "$t"; # quotes required for perl bug
+}
+
+sub m4exit {
+ exit($args[$ab+1]);
+}
+
+sub m4wrap {
+ $m4wrap = $args[$ab+1];
+ "";
+}
+
+sub popdef {
+ eval "\$D{$args[$ab+1]} = pop(@M5'$args[$ab+1])";
+ "";
+}
+
+sub pushdef {
+ eval "push(@M5'$args[$ab+1], \$D{$args[$ab+1]})";
+ $D{$args[$ab+1]} = $args[$ab+2];
+ "";
+}
+
+sub repeat { # repeat(#, expr); evals expr # times; $0 = 0..#-1
+ local($t);
+ for ($args[$ab] = 0; $args[$ab] < $args[$ab+1]; $args[$ab]++) {
+ $t .= &expand($args[$ab+2], '');
+ }
+ $t;
+}
+
+sub shift {
+ join(',', &quotelist(@args[$ab+2..$#args]));
+}
+
+sub substr {
+ $t = substr($args[$ab+1], $args[$ab+2], $args[$ab+3] || 1000000000);
+ "$t"; # quotes required for perl bug
+}
+
+sub syscmd {
+ $m5'sysval = system($args[$ab+1]); #' this is wrong, but close
+ "";
+}
+
+sub undefine {
+ delete $D{$args[$ab+1]};
+ "";
+}
+
+- ---------------------- end ----------------------
+
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl
new file mode 100644
index 0000000000..edffc6b7ba
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl
@@ -0,0 +1,186 @@
+# *** MSUB does some substitutions here ***
+# *** grep for $( ***
+#
+# tries to work like mkdependC
+#
+# ToDo: strip out all the .h junk
+#
+($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/;
+$Usage = "usage: $Pgm: not done yet\n";
+
+$Status = 0; # just used for exit() status
+$Verbose = '';
+$Dashdashes_seen = 0;
+
+$Begin_magic_str = "# DO NOT DELETE: Beginning of C dependencies\n";
+$End_magic_str = "# DO NOT DELETE: End of C dependencies\n";
+$Obj_suffix = '.o';
+@Defines = ();
+$Include_dirs = '';
+$Col_width = 78; # ignored
+$Makefile = '';
+@Src_files = ();
+
+&mangle_command_line_args();
+
+if ( ! $Makefile && -f 'makefile' ) {
+ $Makefile = 'makefile';
+} elsif ( ! $Makefile && -f 'Makefile') {
+ $Makefile = 'Makefile';
+} else {
+ die "$Pgm: no makefile or Makefile found\n";
+}
+
+@Depend_lines = ();
+%Depend_seen = ();
+
+print STDERR "CPP defines=@Defines\n" if $Verbose;
+print STDERR "Include_dirs=$Include_dirs\n" if $Verbose;
+
+foreach $sf (@Src_files) {
+ # just like lit-inputter
+ # except it puts each file through CPP and
+ # a de-commenter (not implemented);
+ # builds up @Depend_lines
+ print STDERR "Here we go for source file: $sf\n" if $Verbose;
+ ($of = $sf) =~ s/\.(c|hc)$/$Obj_suffix/;
+
+ &slurp_file($sf, 'fh00');
+}
+
+# OK, mangle the Makefile
+unlink("$Makefile.bak");
+rename($Makefile,"$Makefile.bak");
+# now copy Makefile.bak into Makefile, rm'ing old dependencies
+# and adding the new
+open(OMKF,"< $Makefile.bak") || die "$Pgm: can't open $Makefile.bak: $!\n";
+open(NMKF,"> $Makefile") || die "$Pgm: can't open $Makefile: $!\n";
+select(NMKF);
+$_ = <OMKF>;
+while ($_ && $_ ne $Begin_magic_str) { # copy through, 'til Begin_magic_str
+ print $_;
+ $_ = <OMKF>;
+}
+while ($_ && $_ ne $End_magic_str) { # delete 'til End_magic_str
+ $_ = <OMKF>;
+}
+# insert dependencies
+print $Begin_magic_str;
+print @Depend_lines;
+print $End_magic_str;
+while (<OMKF>) { # copy the rest through
+ print $_;
+}
+close(NMKF);
+close(OMKF);
+chmod 0444, 'Makefile';
+exit 0;
+
+sub mangle_command_line_args {
+ while($_ = $ARGV[0]) {
+ shift(@ARGV);
+
+ if ( /^--$/ ) {
+ $Dashdashes_seen++;
+
+ } elsif ( /^-D(.*)/ ) { # recognized wherever they occur
+ push(@Defines, $_);
+ } elsif ( /^-I/ ) {
+ $Include_dirs .= " $_";
+
+ } elsif ($Dashdashes_seen != 1) { # not between -- ... --
+ if ( /^-v$/ ) {
+ $Verbose = '-v';
+ } elsif ( /^-f/ ) {
+ $Makefile = &grab_arg_arg($_);
+ } elsif ( /^-o/ ) {
+ $Obj_suffix = &grab_arg_arg($_);
+ } elsif ( /^-bs/ ) {
+ $Begin_magic_str = &grab_arg_arg($_) . "\n";
+ } elsif ( /^-es/ ) {
+ $End_magic_str = &grab_arg_arg($_) . "\n";
+ } elsif ( /^-w/ ) {
+ $Width = &grab_arg_arg($_);
+ } elsif ( /^-/ ) {
+ print STDERR "$Pgm: unknown option ignored: $_\n";
+ } else {
+ push(@Src_files, $_);
+ }
+
+ } elsif ($Dashdashes_seen == 1) { # where we ignore unknown options
+ push(@Src_files,$_) if ! /^-/;
+ }
+ }
+}
+
+sub grab_arg_arg {
+ local($option) = @_;
+ local($rest_of_arg);
+
+ ($rest_of_arg = $option) =~ s/^-.//;
+
+ if ($rest_of_arg) {
+ return($rest_of_arg);
+ } elsif ($#ARGV >= 0) {
+ local($temp) = $ARGV[0]; shift(@ARGV);
+ return($temp);
+ } else {
+ die "$Pgm: no argument following $option option\n";
+ }
+}
+
+sub slurp_file { # follows an example in the `open' item in perl man page
+ local($fname,$fhandle) = @_;
+ local($depend); # tmp
+ $fhandle++; # a string increment
+
+ $fname = &tidy_dir_names($fname);
+
+ unless (open($fhandle, "$(CPP) $Include_dirs @Defines $fname |")) {
+ die "$Pgm: Can't open $fname: $!\n";
+ }
+ line: while (<$fhandle>) {
+ next line if ! /^#/;
+ next line if /^#(ident|pragma)/;
+ chop; # rm trailing newline
+
+ $_ = &tidy_dir_names($_);
+
+ # strip junk off the front and back
+ $_ =~ s/^#\s+\d+\s+//;
+ $_ =~ s/[ 0-9]*$//;
+
+ # a little bit of ad-hoc fiddling now:
+ # don't bother w/ dependencies on /usr/include stuff
+ # don't bother if it looks like a GCC built-in hdr file
+ # don't bother with "literate" .h files (.lh); we'll just
+ # depend on the de-litified versions (which have better info)
+ # don't let a file depend on itself
+ next line if /^\/usr\/include/;
+ next line if /\/gcc-lib\/[^\/\n]+\/[\.0-9]+\/include\//;
+ next line if /\.lh$/;
+ next line if $_ eq $fname;
+
+ print STDERR "$fname :: $_\n" if $Verbose;
+
+ # ToDo: some sanity checks that we still have something reasonable?
+
+ $depend = "$of : $_\n";
+ next line if $Depend_seen{$depend}; # already seen this one...
+
+ # OK, it's a new one.
+ push (@Depend_lines, $depend);
+ $Depend_seen{$depend} = 1;
+ }
+ close($fhandle);
+}
+
+sub tidy_dir_names { # rm various pernicious dir-name combinations...
+ local($str) = @_;
+
+ $str =~ s|/[^/.][^/]*/\.\.||g; # nuke: /<dir>/..
+ $str =~ s|/\.[^.][^/]*/\.\.||g; # nuke: /./.. (and others)
+ $str =~ s|"||g;
+ $str =~ s| \./| |;
+ $str;
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man
new file mode 100644
index 0000000000..999fa12822
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man
@@ -0,0 +1,15 @@
+.TH MKDIRHIER 1 "Release 4" "X Version 11"
+.SH NAME
+mkdirhier \- makes a directory hierarchy
+.SH SYNOPSIS
+.B mkdirhier
+directory ...
+.SH DESCRIPTION
+The
+.I mkdirhier
+command creates the specified directories. Unlike
+.I mkdir
+if any of the parent directories of the specified directory
+do not exist, it creates them as well.
+.SH "SEE ALSO"
+mkdir(1)
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh
new file mode 100644
index 0000000000..739535e118
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+#
+# create a heirarchy of directories
+#
+
+for f in $*; do
+ parts=`echo $f | sed 's,\(.\)/\(.\),\1 \2,g' | sed 's,/$,,'`;
+ path="";
+ for p in $parts; do
+ if [ x"$path" = x ]; then
+ dir=$p;
+ else
+ dir=$path/$p;
+ fi;
+ if [ ! -d $dir ]; then
+ echo mkdir $dir;
+ mkdir $dir;
+ chmod a+rx $dir;
+ fi;
+ path=$dir;
+ done;
+done
+
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh
new file mode 100644
index 0000000000..a00ede08e0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#
+# create a heirarchy of directories (mkdir that makes everything)
+#
+
+USAGE="Usage: $0 master-src-dir-root shadow-src-dir-root filename-from-master-root"
+
+for f in $*; do
+ parts=`echo $f | sed 's,\(.\)/\(.\),\1 \2,g' | sed 's,/$,,'`;
+ path="";
+ for p in $parts; do
+ if [ x"$path" = x ]; then
+ dir=$p;
+ else
+ dir=$path/$p;
+ fi;
+ if [ ! -d $dir ]; then
+ echo mkdir $dir;
+ mkdir $dir;
+ chmod a+rx $dir;
+ fi;
+ path=$dir;
+ done;
+done
+exit 0
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl
new file mode 100644
index 0000000000..9b7c0b98bc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl
@@ -0,0 +1,49 @@
+# "moan" if files in this directory tree appear to be out-of-date
+# with respect to a given "master directory".
+#
+# a utility to use with link trees!
+#
+# usage:
+# % moan-if-old /src/ghc-master-copy
+
+$Verbose = 1;
+$Usage = "usage: moan-if-old master-dir\n";
+
+if ($#ARGV != 0) {
+ die $Usage;
+} else {
+ $Master_dir = $ARGV[0];
+ die "no such dir: $Master_dir\n$Usage" if ! -d $Master_dir;
+}
+
+open(F,"find . -type f -print |") || die "Cannot open find ($!)";
+while (<F>) {
+ chop;
+
+ if (! -f "$Master_dir/$_" && ! &junk_file($_) ) {
+ print STDERR "$_ : not in master directory\n";
+
+ } elsif (-f "$Master_dir/$_") {
+
+ $f1 = "$Master_dir/$_";
+ $f2 = $_;
+
+ @m_dope = stat($f1);
+ @s_dope = stat($f2);
+ if ($m_dope[9] > $s_dope[9]) { # those are modification times...
+ print STDERR "$f1 ($m_dope[9]) > $f2 ($s_dope[9])\n" if $Verbose;
+ print STDERR "$_ : older\n";
+ }
+ }
+}
+close(F);
+
+sub junk_file {
+ local($_) = @_;
+
+ if ( /~$/ || /\.bak$/ || /-(PREV|OLD|SAVE|NEW)$/ ) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl
new file mode 100644
index 0000000000..d7bf6129cb
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl
@@ -0,0 +1,69 @@
+# perl tags, in perl.
+# @(#)ptags 1.2 4/11/91, no copyright. Bugfixes to lm@eng.sun.com.
+
+#In the hack-of-the-hour catagory, a tags file generator for perl. Differences
+#from ctags:
+#
+# 1) Puts a tag in for the filename
+# 2) Puts in multiple tags for the same symbol (I have a hacked version
+# of vi that groks this).
+
+# tag file <vi expresion to find it>
+# catch /u/lm/tmp/eintr.c /^catch() {}$/
+
+if ($#ARGV == -1) {
+ unshift(@ARGV, "-");
+}
+open(STDOUT, ">> TAGS") || die "can't create TAGS"; # partain: NB: APPEND
+while ($_ = shift) {
+ next unless -f $_;
+ print STDERR "$_\n" if $v;
+ do file($_);
+}
+exit;
+
+sub file
+{
+ local($name) = $_[0];
+
+ open(F, $name) || return;
+ $entries = '';
+ $lcnt = 1;
+ $ccnt = 0;
+
+ while (<F>) {
+ # skip the word sub in comments
+ next unless /^[^#]*\bsub\b/;
+ # skip the word sub in a string (one line only, I'm lazy)
+ next if /"[^"]*sub/;
+# print "$name: $. $_" if $d;
+ # demand that "sub" is first on the line (partain)
+ # (the initial > is for some literate perl scripts...)
+ next if ! /^>?\s*sub\s+/;
+ chop;
+ # rm comments
+ s/#.*$//;
+ # and here's the entry...
+ $entries .= "$_\x7f$lcnt,$ccnt\n";
+ $lcnt++;
+ $ccnt += length($_);
+ }
+ # print tag for filename
+ print "\f\n$name,",length($entries),"\n";
+ print $entries;
+}
+
+###I've always used this. Don't recall whom I got it from...
+##
+##--tom
+##
+###!/usr/local/bin/perl
+#open(OUTPUT, "| sort >> TAGS");
+#while (<>) {
+# if (/\bsub\s+(\w+')?(\S+)/) {
+# $func = $2;
+# chop;
+# s,[\\\[\]/.*],\\$&,g;
+# print OUTPUT "$func\t", $ARGV, "\t/^$_\$/\n";
+# }
+#}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl
new file mode 100644
index 0000000000..48e6cc28a8
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl
@@ -0,0 +1,184 @@
+#! /usr/local/bin/perl
+#
+# Given:
+# * a program to run (1st arg)
+# * some "command-line opts" ( -O<opt1> -O<opt2> ... )
+# [default: anything on the cmd line this script doesn't recognise ]
+# the first opt not starting w/ "-" is taken to be an input
+# file and (if it exists) is grepped for "what's going on here"
+# comments (^--!!!).
+# * a file to feed to stdin ( -i<file> ) [default: /dev/null ]
+# * a "time" command to use (-t <cmd>).
+#
+# * alternatively, a "-script <script>" argument says: run the
+# named Bourne-shell script to do the test. It's passed the
+# pgm-to-run as the one-and-only arg.
+#
+# Run the program with those options and that input, and check:
+# if we get...
+#
+# * an expected exit status ( -x <val> ) [ default 0 ]
+# * expected output on stdout ( -o1 <file> ) [ default /dev/null ]
+# * expected output on stderr ( -o2 <file> ) [ default /dev/null ]
+#
+# (if the expected-output files' names end in .Z, then
+# they are uncompressed before doing the comparison)
+#
+# (This is supposed to be a "prettier" replacement for runstdtest.)
+#
+($Pgm = $0) =~ s|.*/||;
+$Verbose = 0;
+$Status = 0;
+@PgmArgs = ();
+$PgmExitStatus = 0;
+$PgmStdinFile = '/dev/null';
+$PgmStdoutFile = '/dev/null';
+$PgmStderrFile = '/dev/null';
+$AltScript = '';
+$TimeCmd = '';
+
+die "$Pgm: program to run not given as first argument\n" if $#ARGV < 0;
+$ToRun = $ARGV[0]; shift(@ARGV);
+# avoid picking up same-named thing from somewhere else on $PATH...
+$ToRun = "./$ToRun" if $ToRun !~ /^\//;
+
+arg: while ($_ = $ARGV[0]) {
+ shift(@ARGV);
+
+ /^-v$/ && do { $Verbose = 1; next arg; };
+ /^-O(.*)/ && do { push(@PgmArgs, &grab_arg_arg('-O',$1)); next arg; };
+ /^-i(.*)/ && do { $PgmStdinFile = &grab_arg_arg('-i',$1);
+ $Status++,
+ print STDERR "$Pgm: bogus -i input file: $PgmStdinFile\n"
+ if ! -f $PgmStdinFile;
+ next arg; };
+ /^-x(.*)/ && do { $PgmExitStatus = &grab_arg_arg('-x',$1);
+ $Status++ ,
+ print STDERR "$Pgm: bogus -x expected exit status: $PgmExitStatus\n"
+ if $PgmExitStatus !~ /^\d+$/;
+ next arg; };
+ /^-o1(.*)/ && do { $PgmStdoutFile = &grab_arg_arg('-o1',$1);
+ $Status++ ,
+ print STDERR "$Pgm: bogus -o1 expected-output file: $PgmStdoutFile\n"
+ if ! -f $PgmStdoutFile;
+ next arg; };
+ /^-o2(.*)/ && do { $PgmStderrFile = &grab_arg_arg('-o2',$1);
+ $Status++,
+ print STDERR "$Pgm: bogus -o2 expected-stderr file: $PgmStderrFile\n"
+ if ! -f $PgmStderrFile;
+ next arg; };
+ /^-script(.*)/ && do { $AltScript = &grab_arg_arg('-script',$1);
+ next arg; };
+ /^-t(.*)/ && do { $TimeCmd = &grab_arg_arg('-t', $1); next arg; };
+
+ # anything else is taken to be a pgm arg
+ push(@PgmArgs, $_);
+}
+exit 1 if $Status;
+
+# tidy up the pgm args:
+# (1) look for the "first input file"
+# and grep it for "interesting" comments (--!!! )
+# (2) quote any args w/ whitespace in them.
+$grep_done = 0;
+foreach $a ( @PgmArgs ) {
+ if (! $grep_done && $a !~ /^-/ && -f $a) {
+ print `egrep "^--!!!" $a`;
+ $grep_done = 1;
+ }
+ if ($a =~ /\s/ || $a =~ /'/) {
+ $a =~ s/'/\\'/g; # backslash the quotes;
+ $a = "\"$a\""; # quote the arg
+ }
+}
+
+if ($AltScript ne '') {
+ local($to_do);
+ $to_do = `cat $AltScript`;
+ # glue in pgm to run...
+ $* = 1;
+ $to_do =~ s/^\$1 /$ToRun /;
+ &run_something($to_do);
+ exit 0;
+# exec "$AltScript $ToRun";
+# print STDERR "Failed to exec!!! $AltScript $ToRun\n";
+# exit 1;
+}
+
+# OK, so we're gonna do the normal thing...
+
+$Script = <<EOSCRIPT;
+#! /bin/sh
+myexit=0
+diffsShown=0
+$TimeCmd /bin/sh -c \'$ToRun @PgmArgs < $PgmStdinFile 1> $(TMPDIR)/runtest$$.1 2> $(TMPDIR)/runtest$$.2\'
+progexit=\$?
+if [ \$progexit -ne $PgmExitStatus ]; then
+ echo $ToRun @PgmArgs \\< $PgmStdinFile
+ echo expected exit status $PgmExitStatus not seen \\; got \$progexit
+ myexit=1
+else
+ if cmp -s $PgmStdoutFile $(TMPDIR)/runtest$$.1 ; then
+ echo -n "" # no-op
+ else
+ echo $ToRun @PgmArgs \\< $PgmStdinFile
+ echo expected stdout not matched by reality
+ diff -c1 $PgmStdoutFile $(TMPDIR)/runtest$$.1
+ myexit=1
+ diffsShown=1
+ fi
+fi
+if cmp -s $PgmStderrFile $(TMPDIR)/runtest$$.2 ; then
+ echo -n "" # no-op
+else
+ echo $ToRun @PgmArgs \\< $PgmStdinFile
+ echo expected stderr not matched by reality
+ diff -c1 $PgmStderrFile $(TMPDIR)/runtest$$.2
+ myexit=1
+ diffsShown=1
+fi
+$(RM) core $(TMPDIR)/runtest$$.1 $(TMPDIR)/runtest$$.2
+exit \$myexit
+EOSCRIPT
+
+&run_something($Script);
+# print $Script if $Verbose;
+# open(SH, "| /bin/sh") || die "Can't open shell pipe\n";
+# print SH $Script;
+# close(SH);
+
+exit 0;
+
+sub grab_arg_arg {
+ local($option, $rest_of_arg) = @_;
+
+ if ($rest_of_arg) {
+ return($rest_of_arg);
+ } elsif ($#ARGV >= 0) {
+ local($temp) = $ARGV[0]; shift(@ARGV);
+ return($temp);
+ } else {
+ print STDERR "$Pgm: no argument following $option option\n";
+ $Status++;
+ }
+}
+
+sub run_something {
+ local($str_to_do) = @_;
+
+ print STDERR "$str_to_do\n" if $Verbose;
+
+ local($return_val) = 0;
+ system($str_to_do);
+ $return_val = $?;
+
+ if ($return_val != 0) {
+#ToDo: this return-value mangling is wrong
+# local($die_msg) = "$Pgm: execution of the $tidy_name had trouble";
+# $die_msg .= " (program not found)" if $return_val == 255;
+# $die_msg .= " ($!)" if $Verbose && $! != 0;
+# $die_msg .= "\n";
+
+ exit (($return_val == 0) ? 0 : 1);
+ }
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/zap-if-same.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/zap-if-same.prl
new file mode 100644
index 0000000000..1bdb69ca99
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/zap-if-same.prl
@@ -0,0 +1,50 @@
+# "zap" files in a directory tree if they're the same as somewhere else
+#
+# zap normally means "rm", but "-s" means to put a symlink in place instead.
+#
+# usage:
+# # delete all files in this dir that are same as in master copy...
+# % zap-if-same /src/ghc-master-copy
+# # use lndir to put in mere links...
+# % lndir /src/ghc-master-copy
+#
+# a similar effect can be had with just...
+# % zap-if-same -s /src/ghc-master-copy
+
+$Usage = "usage: zap-if-same [-s] master-dir\n";
+
+$Action = 'rm';
+
+if ($#ARGV >= 0 && $ARGV[0] eq '-s') {
+ $Action = 'link';
+ shift;
+}
+
+if ($#ARGV != 0) {
+ die $Usage;
+} else {
+ $Master_dir = $ARGV[0];
+ die "no such dir: $Master_dir\n$Usage" if ! -d $Master_dir;
+}
+
+open(F,"find . -type f -print |") || die "Cannot open find ($!)";
+while (<F>) {
+ chop;
+
+ if ( -f "$Master_dir/$_" && &same_contents($_) ) { # ToDo: & not same file?
+ print STDERR "$_ ...\n";
+ unlink $_;
+ if ($Action eq 'link') {
+ symlink("$Master_dir/$_", $_);
+ }
+ }
+}
+close(F);
+
+sub same_contents {
+ local($f) = @_;
+
+ local($return_val) = 0;
+ $return_val = system("cmp -s $Master_dir/$f $f") >> 8;
+ ($return_val == 0) ? 1 : 0;
+}
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/verbatim/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/Jmakefile
new file mode 100644
index 0000000000..3a2b000b98
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/Jmakefile
@@ -0,0 +1,4 @@
+BuildPgmFromCFiles(verbatim,verbatim.o,-ll,)
+InstallBinaryTarget(verbatim,$(INSTBINDIR))
+
+CDependTarget( $(SRCS_C) )
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.c b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.c
new file mode 100644
index 0000000000..9d82abe2d9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.c
@@ -0,0 +1,533 @@
+# include "stdio.h"
+# define U(x) x
+# define NLSTATE yyprevious=YYNEWLINE
+# define BEGIN yybgin = yysvec + 1 +
+# define INITIAL 0
+# define YYLERR yysvec
+# define YYSTATE (yyestate-yysvec-1)
+# define YYOPTIM 1
+# define YYLMAX BUFSIZ
+# define output(c) putc(c,yyout)
+# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
+# define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;}
+# define yymore() (yymorfg=1)
+# define ECHO fprintf(yyout, "%s",yytext)
+# define REJECT { nstr = yyreject(); goto yyfussy;}
+int yyleng; extern char yytext[];
+int yymorfg;
+extern char *yysptr, yysbuf[];
+int yytchar;
+FILE *yyin = {stdin}, *yyout = {stdout};
+extern int yylineno;
+struct yysvf {
+ struct yywork *yystoff;
+ struct yysvf *yyother;
+ int *yystops;};
+struct yysvf *yyestate;
+extern struct yysvf yysvec[], *yybgin;
+ /* This Lex script acts as a filter to pre-process Latex files.
+ It surrounds groups of lines beginning with a ">" sign, and
+ preceded and followed by a blank line, with \begin{verbatim}
+ and \end{verbatim}. The ">" may be preceded by a digit or digit
+ range (eg 4>, 2-5>, 3->); in this case the digits are removed.
+ They are meant to be used for filtering out versions.
+ It takes words surrounded with @ signs (thus @letrec@) and makes them
+ come out in typewriter font, regardless of the current mode.
+ */
+# define NORM 2
+# define VERB 4
+# define MIRANDA 6
+# define VERBATIM 8
+# define VERBATIMSIM 10
+#define PUSH states[top++] =
+#define POP BEGIN states[--top]
+# define YYNEWLINE 10
+yylex(){
+int nstr; extern int yyprevious;
+ int states[256];
+ int top;
+ BEGIN NORM;
+ top = 0;
+while((nstr = yylook()) >= 0)
+yyfussy: switch(nstr){
+case 0:
+if(yywrap()) return(0); break;
+case 1:
+ { printf ("@"); }
+break;
+case 2:
+ { printf ("\\mbox{\\tt "); PUSH NORM; BEGIN VERB; }
+break;
+case 3:
+ { printf ("}"); POP; }
+break;
+case 4:
+ { printf ("}\\\\{}\n\\mbox{\\tt "); }
+break;
+case 5:
+ { printf ("\\ "); }
+break;
+case 6:
+ { printf ("@"); }
+break;
+case 7:
+ { printf ("{\\char'43}"); }
+break;
+case 8:
+ { printf ("{\\char'44}"); }
+break;
+case 9:
+ { printf ("{\\char'45}"); }
+break;
+case 10:
+ { printf ("{\\char'46}"); }
+break;
+case 11:
+ { printf ("{\\char'176}"); }
+break;
+case 12:
+ { printf ("{\\char'137}"); }
+break;
+case 13:
+ { printf ("{\\char'136}"); }
+break;
+case 14:
+ { printf ("{\\char'134}"); }
+break;
+case 15:
+ { printf ("{\\char'173}"); }
+break;
+case 16:
+ { printf ("{\\char'175}"); }
+break;
+case 17:
+ { printf( "\\begin{verbatim}\n" );
+ PUSH NORM; BEGIN VERBATIMSIM; }
+break;
+case 18:
+{ printf( "\\end{verbatim}\n" ); POP; }
+break;
+case 19:
+{ printf( "\\begin{verbatim}" );
+ PUSH NORM; BEGIN VERBATIM; }
+break;
+case 20:
+{ printf( "\\end{verbatim}" ); POP; }
+break;
+case 21:
+{ printf ("\\begin{verbatim}\n>" );
+ PUSH NORM; BEGIN MIRANDA; }
+break;
+case 22:
+{ printf( "\n>" ); }
+break;
+case 23:
+ { printf ("\\end{verbatim}\n"); POP; }
+break;
+case -1:
+break;
+default:
+fprintf(yyout,"bad switch yylook %d",nstr);
+} return(0); }
+/* end of yylex */
+int yyvstop[] = {
+0,
+
+2,
+0,
+
+2,
+0,
+
+4,
+0,
+
+5,
+0,
+
+7,
+0,
+
+8,
+0,
+
+9,
+0,
+
+10,
+0,
+
+3,
+0,
+
+14,
+0,
+
+13,
+0,
+
+12,
+0,
+
+15,
+0,
+
+16,
+0,
+
+11,
+0,
+
+23,
+0,
+
+1,
+0,
+
+21,
+0,
+
+17,
+0,
+
+6,
+0,
+
+22,
+0,
+
+18,
+0,
+
+20,
+0,
+
+19,
+0,
+0};
+# define YYTYPE char
+struct yywork { YYTYPE verify, advance; } yycrank[] = {
+0,0, 0,0, 0,0, 0,0,
+0,0, 0,0, 0,0, 0,0,
+0,0, 0,0, 0,0, 0,0,
+4,15, 5,17, 7,30, 8,31,
+33,43, 0,0, 0,0, 0,0,
+0,0, 0,0, 0,0, 0,0,
+0,0, 0,0, 16,38, 0,0,
+0,0, 0,0, 0,0, 0,0,
+0,0, 0,0, 0,0, 5,18,
+0,0, 0,0, 5,19, 5,20,
+5,21, 5,22, 0,0, 0,0,
+0,0, 0,0, 0,0, 0,0,
+36,45, 40,46, 0,0, 45,45,
+45,45, 45,45, 45,45, 45,45,
+45,45, 45,45, 45,45, 45,45,
+45,45, 0,0, 0,0, 0,0,
+0,0, 3,13, 4,16, 5,23,
+12,33, 13,34, 15,36, 15,36,
+15,36, 15,36, 15,36, 15,36,
+15,36, 15,36, 15,36, 15,36,
+16,34, 23,39, 0,0, 0,0,
+15,37, 0,0, 0,0, 0,0,
+0,0, 0,0, 0,0, 0,0,
+0,0, 3,14, 4,14, 5,24,
+9,32, 5,25, 5,26, 0,0,
+0,0, 14,35, 30,40, 30,40,
+30,40, 30,40, 30,40, 30,40,
+30,40, 30,40, 30,40, 30,40,
+32,42, 35,44, 42,47, 44,48,
+30,41, 47,49, 48,50, 53,55,
+56,58, 57,59, 59,61, 60,62,
+50,52, 62,64, 5,27, 63,65,
+5,28, 5,29, 46,46, 46,46,
+46,46, 46,46, 46,46, 46,46,
+46,46, 46,46, 46,46, 46,46,
+49,51, 51,53, 52,54, 54,56,
+55,57, 58,60, 61,63, 64,66,
+65,67, 66,68, 67,69, 68,70,
+70,71, 0,0, 0,0, 0,0,
+0,0};
+struct yysvf yysvec[] = {
+0, 0, 0,
+yycrank+0, 0, 0,
+yycrank+0, 0, 0,
+yycrank+1, 0, 0,
+yycrank+2, 0, 0,
+yycrank+3, 0, 0,
+yycrank+0, yysvec+5, 0,
+yycrank+4, 0, 0,
+yycrank+5, 0, 0,
+yycrank+4, 0, 0,
+yycrank+0, yysvec+9, 0,
+yycrank+0, 0, 0,
+yycrank+4, 0, 0,
+yycrank+5, 0, yyvstop+1,
+yycrank+3, 0, 0,
+yycrank+22, 0, 0,
+yycrank+16, 0, yyvstop+3,
+yycrank+0, 0, yyvstop+5,
+yycrank+0, 0, yyvstop+7,
+yycrank+0, 0, yyvstop+9,
+yycrank+0, 0, yyvstop+11,
+yycrank+0, 0, yyvstop+13,
+yycrank+0, 0, yyvstop+15,
+yycrank+17, 0, yyvstop+17,
+yycrank+0, 0, yyvstop+19,
+yycrank+0, 0, yyvstop+21,
+yycrank+0, 0, yyvstop+23,
+yycrank+0, 0, yyvstop+25,
+yycrank+0, 0, yyvstop+27,
+yycrank+0, 0, yyvstop+29,
+yycrank+54, 0, 0,
+yycrank+0, yysvec+30, yyvstop+31,
+yycrank+11, 0, 0,
+yycrank+6, 0, 0,
+yycrank+0, 0, yyvstop+33,
+yycrank+12, 0, 0,
+yycrank+3, yysvec+15, 0,
+yycrank+0, 0, yyvstop+35,
+yycrank+0, 0, yyvstop+37,
+yycrank+0, 0, yyvstop+39,
+yycrank+4, yysvec+30, 0,
+yycrank+0, 0, yyvstop+41,
+yycrank+4, 0, 0,
+yycrank+0, 0, yyvstop+43,
+yycrank+12, 0, 0,
+yycrank+3, yysvec+15, 0,
+yycrank+82, yysvec+30, 0,
+yycrank+17, 0, 0,
+yycrank+13, 0, 0,
+yycrank+17, 0, 0,
+yycrank+14, 0, 0,
+yycrank+23, 0, 0,
+yycrank+19, 0, 0,
+yycrank+18, 0, 0,
+yycrank+25, 0, 0,
+yycrank+30, 0, 0,
+yycrank+19, 0, 0,
+yycrank+23, 0, 0,
+yycrank+31, 0, 0,
+yycrank+25, 0, 0,
+yycrank+25, 0, 0,
+yycrank+30, 0, 0,
+yycrank+28, 0, 0,
+yycrank+22, 0, 0,
+yycrank+31, 0, 0,
+yycrank+39, 0, 0,
+yycrank+44, 0, 0,
+yycrank+25, 0, 0,
+yycrank+42, 0, 0,
+yycrank+0, 0, yyvstop+45,
+yycrank+27, 0, 0,
+yycrank+0, 0, yyvstop+47,
+0, 0, 0};
+struct yywork *yytop = yycrank+152;
+struct yysvf *yybgin = yysvec+1;
+char yymatch[] = {
+00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,
+'0' ,'0' ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,
+0};
+char yyextra[] = {
+0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,
+0};
+#ifndef lint
+static char ncform_sccsid[] = "@(#)ncform 1.6 88/02/08 SMI"; /* from S5R2 1.2 */
+#endif
+
+int yylineno =1;
+# define YYU(x) x
+# define NLSTATE yyprevious=YYNEWLINE
+char yytext[YYLMAX];
+struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
+char yysbuf[YYLMAX];
+char *yysptr = yysbuf;
+int *yyfnd;
+extern struct yysvf *yyestate;
+int yyprevious = YYNEWLINE;
+yylook(){
+ register struct yysvf *yystate, **lsp;
+ register struct yywork *yyt;
+ struct yysvf *yyz;
+ int yych, yyfirst;
+ struct yywork *yyr;
+# ifdef LEXDEBUG
+ int debug;
+# endif
+ char *yylastch;
+ /* start off machines */
+# ifdef LEXDEBUG
+ debug = 0;
+# endif
+ yyfirst=1;
+ if (!yymorfg)
+ yylastch = yytext;
+ else {
+ yymorfg=0;
+ yylastch = yytext+yyleng;
+ }
+ for(;;){
+ lsp = yylstate;
+ yyestate = yystate = yybgin;
+ if (yyprevious==YYNEWLINE) yystate++;
+ for (;;){
+# ifdef LEXDEBUG
+ if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
+# endif
+ yyt = yystate->yystoff;
+ if(yyt == yycrank && !yyfirst){ /* may not be any transitions */
+ yyz = yystate->yyother;
+ if(yyz == 0)break;
+ if(yyz->yystoff == yycrank)break;
+ }
+ *yylastch++ = yych = input();
+ yyfirst=0;
+ tryagain:
+# ifdef LEXDEBUG
+ if(debug){
+ fprintf(yyout,"char ");
+ allprint(yych);
+ putchar('\n');
+ }
+# endif
+ yyr = yyt;
+ if ( (int)yyt > (int)yycrank){
+ yyt = yyr + yych;
+ if (yyt <= yytop && yyt->verify+yysvec == yystate){
+ if(yyt->advance+yysvec == YYLERR) /* error transitions */
+ {unput(*--yylastch);break;}
+ *lsp++ = yystate = yyt->advance+yysvec;
+ goto contin;
+ }
+ }
+# ifdef YYOPTIM
+ else if((int)yyt < (int)yycrank) { /* r < yycrank */
+ yyt = yyr = yycrank+(yycrank-yyt);
+# ifdef LEXDEBUG
+ if(debug)fprintf(yyout,"compressed state\n");
+# endif
+ yyt = yyt + yych;
+ if(yyt <= yytop && yyt->verify+yysvec == yystate){
+ if(yyt->advance+yysvec == YYLERR) /* error transitions */
+ {unput(*--yylastch);break;}
+ *lsp++ = yystate = yyt->advance+yysvec;
+ goto contin;
+ }
+ yyt = yyr + YYU(yymatch[yych]);
+# ifdef LEXDEBUG
+ if(debug){
+ fprintf(yyout,"try fall back character ");
+ allprint(YYU(yymatch[yych]));
+ putchar('\n');
+ }
+# endif
+ if(yyt <= yytop && yyt->verify+yysvec == yystate){
+ if(yyt->advance+yysvec == YYLERR) /* error transition */
+ {unput(*--yylastch);break;}
+ *lsp++ = yystate = yyt->advance+yysvec;
+ goto contin;
+ }
+ }
+ if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
+# ifdef LEXDEBUG
+ if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
+# endif
+ goto tryagain;
+ }
+# endif
+ else
+ {unput(*--yylastch);break;}
+ contin:
+# ifdef LEXDEBUG
+ if(debug){
+ fprintf(yyout,"state %d char ",yystate-yysvec-1);
+ allprint(yych);
+ putchar('\n');
+ }
+# endif
+ ;
+ }
+# ifdef LEXDEBUG
+ if(debug){
+ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
+ allprint(yych);
+ putchar('\n');
+ }
+# endif
+ while (lsp-- > yylstate){
+ *yylastch-- = 0;
+ if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
+ yyolsp = lsp;
+ if(yyextra[*yyfnd]){ /* must backup */
+ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
+ lsp--;
+ unput(*yylastch--);
+ }
+ }
+ yyprevious = YYU(*yylastch);
+ yylsp = lsp;
+ yyleng = yylastch-yytext+1;
+ yytext[yyleng] = 0;
+# ifdef LEXDEBUG
+ if(debug){
+ fprintf(yyout,"\nmatch ");
+ sprint(yytext);
+ fprintf(yyout," action %d\n",*yyfnd);
+ }
+# endif
+ return(*yyfnd++);
+ }
+ unput(*yylastch);
+ }
+ if (yytext[0] == 0 /* && feof(yyin) */)
+ {
+ yysptr=yysbuf;
+ return(0);
+ }
+ yyprevious = yytext[0] = input();
+ if (yyprevious>0)
+ output(yyprevious);
+ yylastch=yytext;
+# ifdef LEXDEBUG
+ if(debug)putchar('\n');
+# endif
+ }
+ }
+yyback(p, m)
+ int *p;
+{
+if (p==0) return(0);
+while (*p)
+ {
+ if (*p++ == m)
+ return(1);
+ }
+return(0);
+}
+ /* the following are only used in the lex library */
+yyinput(){
+ return(input());
+ }
+yyoutput(c)
+ int c; {
+ output(c);
+ }
+yyunput(c)
+ int c; {
+ unput(c);
+ }
diff --git a/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.lex b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.lex
new file mode 100644
index 0000000000..0263a26620
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.lex
@@ -0,0 +1,57 @@
+
+ /* This Lex script acts as a filter to pre-process Latex files.
+
+ It surrounds groups of lines beginning with a ">" sign, and
+ preceded and followed by a blank line, with \begin{verbatim}
+ and \end{verbatim}. The ">" may be preceded by a digit or digit
+ range (eg 4>, 2-5>, 3->); in this case the digits are removed.
+ They are meant to be used for filtering out versions.
+
+ It takes words surrounded with @ signs (thus @letrec@) and makes them
+ come out in typewriter font, regardless of the current mode.
+ */
+
+%START NORM VERB MIRANDA VERBATIM VERBATIMSIM
+sp [ \t]*
+nl {sp}\n{sp}
+miranda ([0-9]+(\-([0-9]+)?)?)?>
+%{
+#define PUSH states[top++] =
+#define POP BEGIN states[--top]
+%}
+%%
+ int states[256];
+ int top;
+ BEGIN NORM;
+ top = 0;
+<NORM>@@ { printf ("@"); }
+<NORM>@ { printf ("\\mbox{\\tt "); PUSH NORM; BEGIN VERB; }
+<VERB>@ { printf ("}"); POP; }
+<VERB>\n { printf ("}\\\\{}\n\\mbox{\\tt "); }
+<VERB>" " { printf ("\\ "); }
+<VERB>@@ { printf ("@"); }
+<VERB>\# { printf ("{\\char'43}"); }
+<VERB>\$ { printf ("{\\char'44}"); }
+<VERB>\% { printf ("{\\char'45}"); }
+<VERB>\& { printf ("{\\char'46}"); }
+<VERB>\~ { printf ("{\\char'176}"); }
+<VERB>\_ { printf ("{\\char'137}"); }
+<VERB>\^ { printf ("{\\char'136}"); }
+<VERB>\\ { printf ("{\\char'134}"); }
+<VERB>\{ { printf ("{\\char'173}"); }
+<VERB>\} { printf ("{\\char'175}"); }
+
+<NORM>^@\n { printf( "\\begin{verbatim}\n" );
+ PUSH NORM; BEGIN VERBATIMSIM; }
+<VERBATIMSIM>^@\n { printf( "\\end{verbatim}\n" ); POP; }
+
+<NORM>\\"begin{verbatim}" { printf( "\\begin{verbatim}" );
+ PUSH NORM; BEGIN VERBATIM; }
+<VERBATIM>\\"end{verbatim}" { printf( "\\end{verbatim}" ); POP; }
+
+<NORM>^\n{miranda} { printf ("\\begin{verbatim}\n>" );
+ PUSH NORM; BEGIN MIRANDA; }
+<MIRANDA>\n{miranda} { printf( "\n>" ); }
+<MIRANDA>^\n { printf ("\\end{verbatim}\n"); POP; }
+
+
diff --git a/web/glasgow/lit2x-0.16/literate/Jmakefile b/web/glasgow/lit2x-0.16/literate/Jmakefile
new file mode 100644
index 0000000000..09f11b31f3
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/Jmakefile
@@ -0,0 +1,131 @@
+#define IHaveSubdirs
+
+#if IncludeTestDirsInBuild == YES
+#define __lit_tests_dir tests
+#else
+#define __lit_tests_dir /* nothing */
+#endif
+
+SUBDIRS = __lit_tests_dir \
+ info-utils \
+ doc
+
+
+LitSuffixRule(.lprl,.prl)
+LitSuffixRule(.llex,.lex)
+
+/* stuff to have before we get going */
+MsubNeededHere(lit2stuff lit-inputter)
+
+/* _must_ use special lit2pgm to re-build the lit2pgm source here */
+LIT2PGM = ./lit2pgm.BOOT -Alit2pgm
+
+LIT2PGM_OPTS = -q /* so we go fast; not really necessary (ToDo) */
+
+/* BUILDING STUFF ================================================= */
+/****** the driver script "lit2stuff" *******/
+
+/* has host-platform type wired in, so in BIN, not SCRIPT, dir */
+
+/* slam INSTLIBDIR_LITERATE, INSTDATADIR_LITERATE, TMPDIR from Makefile into lit2stuff */
+MsubMakefileDependentProgramScriptTarget(PerlCmd,lit2stuff,lit2stuff.prl,/*no flags*/,/*Makefile*/)
+/****** the names by which "lit2stuff" may be invoked */
+LinkTarget(lit2pgm,lit2stuff)
+LinkTarget(lit2texi,lit2stuff)
+LinkTarget(lit2latex,lit2stuff)
+LinkTarget(mkdependlit,lit2stuff)
+LinkTarget(lit2changelog,lit2stuff)
+LinkTarget(lit2text,lit2stuff)
+
+/* and the mangled source... */
+LitDocRootTargetWithNamedOutput(lit2stuff,lprl,lit2stuff-standalone)
+
+/****** all the support code that is slurped in or fired up by "lit2stuff"
+******/
+
+/* these two (lit-deatify & lit-inputter) are executables: */
+lit-deatify.c : lit-deatify.lex /* a flex program ... */
+ $(RM) lit-deatify.c
+ flex -t lit-deatify.lex > lit-deatify.c
+
+BuildPgmFromCFiles(lit-deatify,lit-deatify.o,,)
+
+MsubProgramScriptTarget(PerlCmd,lit-inputter,lit-inputter.prl,/*no flags*/,/**/)
+
+/* LaTeX macros to support the enterprise;
+ * not kept in the TeX directories because we want to
+ * know where it is so we can be sure to \input the right version
+*/
+LITDATASTUFF = lit-2changes.prl \
+ lit-2depend.prl \
+ lit-2doc-c.prl \
+ lit-2doc-hs.prl \
+ lit-2doc-jm.prl \
+ lit-2doc-lex.prl \
+ lit-2doc-none.prl \
+ lit-2doc-prl.prl \
+ lit-2doc.prl \
+ lit-2latex-c.prl \
+ lit-2latex-hs.prl \
+ lit-2latex-jm.prl \
+ lit-2latex-lex.prl \
+ lit-2latex-none.prl \
+ lit-2latex-prl.prl \
+ lit-2latex.prl \
+ lit-2pgm-c.prl \
+ lit-2pgm-hs.prl \
+ lit-2pgm-jm.prl \
+ lit-2pgm-lex.prl \
+ lit-2pgm-none.prl \
+ lit-2pgm-prl.prl \
+ lit-2pgm.prl \
+ lit-2texi-c.prl \
+ lit-2texi-hs.prl \
+ lit-2texi-jm.prl \
+ lit-2texi-lex.prl \
+ lit-2texi-none.prl \
+ lit-2texi-prl.prl \
+ lit-2texi.prl \
+ lit-2text.prl \
+ lit-globals.prl \
+ lit-link-globals.prl \
+ lit-linker.prl \
+ lit-reader.prl
+
+AllTarget($(LITDATASTUFF))
+
+litdatastuff : $(LITDATASTUFF)
+
+/* all the rest of the things are built with the default .lprl->.prl rule */
+
+/* INSTALLING STUFF =============================================== */
+
+INSTDATADIR_LITERATE = $(INSTDATADIR)/literate
+INSTLIBDIR_LITERATE = $(INSTDATADIR_LITERATE)/$(HOSTPLATFORM)
+
+MakeDirectories(install, $(INSTBINDIR) $(INSTLIBDIR_LITERATE) $(INSTDATADIR_LITERATE))
+
+InstallMsubbedScriptTarget(PerlCmd,lit2stuff,lit2stuff.prl,$(INSTBINDIR))
+InstallLinkTarget(lit2pgm,lit2stuff,$(INSTBINDIR))
+InstallLinkTarget(lit2texi,lit2stuff,$(INSTBINDIR))
+InstallLinkTarget(lit2latex,lit2stuff,$(INSTBINDIR))
+InstallLinkTarget(mkdependlit,lit2stuff,$(INSTBINDIR))
+InstallLinkTarget(lit2changelog,lit2stuff,$(INSTBINDIR))
+InstallLinkTarget(lit2text,lit2stuff,$(INSTBINDIR))
+
+InstallBinaryTarget(lit-deatify, $(INSTLIBDIR_LITERATE))
+InstallScriptTarget(lit-inputter, $(INSTLIBDIR_LITERATE))
+
+InstallDataTarget(lit-style.tex, $(INSTDATADIR_LITERATE))
+InstallTarget(litdatastuff)
+InstallMultNonExecTargets(litdatastuff, $(LITDATASTUFF), $(INSTDATADIR_LITERATE))
+
+/* OTHER STUFF ==================================================== */
+ExtraStuffToClean( lit2stuff.prl li-inputter.prl $(LITDATASTUFF) )
+
+ClearTagsFile()
+LITDATA_LPRLS = $(LITDATASTUFF:.prl=.lprl)
+PerlTagsTarget( lit2stuff.lprl lit-inputter.lprl $(LITDATA_LPRLS) )
+EtagsNeededHere(tags) /* need this to do "make tags" */
+CTagsTarget( lit-deatify.lex )
+/* LaTeX style file ? */
diff --git a/web/glasgow/lit2x-0.16/literate/MAIL.ireland b/web/glasgow/lit2x-0.16/literate/MAIL.ireland
new file mode 100644
index 0000000000..d9e94e8bbb
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/MAIL.ireland
@@ -0,0 +1,76 @@
+From E.Ireland@massey.ac.nz Wed Aug 21 01:56:20 1991
+X-VM-Attributes: [nil nil nil nil t]
+Status: RO
+Via: uk.ac.nsf; Wed, 21 Aug 91 01:56:14 BST
+Received: from vax.nsfnet-relay.ac.uk by sun2.nsfnet-relay.ac.uk
+ with SMTP inbound id <26022-5@sun2.nsfnet-relay.ac.uk>;
+ Wed, 21 Aug 1991 01:54:16 +0100
+Received: from [130.123.1.7] by vax.NSFnet-Relay.AC.UK via NSFnet with SMTP
+ id aa23150; 21 Aug 91 1:39 BST
+Received: from sis-a by cc-server4.massey.ac.nz (5.64+IDA-1.3.1) id AA15464;
+ Wed, 21 Aug 91 12:48:43 +1200
+Received: from sis-c.sis by sis-a (4.1/SMI-4.0) id AA00751;
+ Wed, 21 Aug 91 12:48:26 NZS
+Message-Id: <9108210048.AA00751@sis-a>
+Received: by sis-c.sis (4.1/SMI-4.1) id AA13550; Wed, 21 Aug 91 12:48:20 NZS
+In-Reply-To: Will Partain's message of Sat, 6 Jul 91 04:21:31 BST <16225.9107060321@dcs.glasgow.ac.uk>
+From: E.Ireland@massey.ac.nz
+To: partain, simonpj
+Subject: Literate Haskell:
+Date: Wed, 21 Aug 91 12:48:26 NZS
+
+Will and/or Simon,
+
+I have all the literate Haskell stuff up and running here, but I can't see how
+to do a few of the things that I thought I would be able to. If I put code in
+code or pseudocode environments, it is typeset flush with the left margin. I
+would like
+
+\begin{code}
+f x y = x + y
+\end{code}
+
+to typeset as
+
+ > f x y = x + y
+
+and would like
+
+\begin{pseudocode}
+f x y = x + y
+\end{pseudocode}
+
+to typeset as
+
+ f x y = x + y
+
+After a section title or code environment, the second and subsequent following
+paragraphs should have the first line indented, but this is not happening. I
+don't remember having to specify anything to LaTeX in the past to get this
+behaviour, but I am not a LaTeX hacker, and neither is any member of our
+support staff. How can I fix this?
+
+Ideally, I would like the code and pseudocode environments to be indented by
+the same amount as the indentation for the first line of a `subsequent'
+paragraph. Thus I would like things to appear much as they do in the recent
+S.P.E. article on Lambda Lifting by Simon and David Lester, but with a smaller
+amount of indentation for code environments.
+
+In summary, my questions are:
+
+(1) How do I get the first line indentation for `subsequent' paragraphs?
+
+(2) How do I get the same amount of indentation for code environments?
+
+(3) How do I get the '>'s for code environments (but not for pseudocode
+ environments)?
+
+I would appreciate a prompt reply: I am hoping to complete a paper which has a
+3 Sept. deadline.
+
+ Thanks in advance,
+_______________________________________________________________________________
+
+E.Ireland@massey.ac.nz Evan Ireland, Department of Computer Science,
+ +64-6-3569099 x8541 Massey University, Palmerston North, New Zealand.
+
diff --git a/web/glasgow/lit2x-0.16/literate/Makefile.BOOT b/web/glasgow/lit2x-0.16/literate/Makefile.BOOT
new file mode 100644
index 0000000000..95ed4970f1
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/Makefile.BOOT
@@ -0,0 +1,58 @@
+# hand-hacked Makefile to boot the "make world" process
+#---------------------------------------------------------------------
+
+# Platform-specific configuration stuff was read from: sun.cf
+
+SHELL = /bin/sh
+PATHSEP = /
+
+TOP = ..
+CURRENT_DIR = ./literate
+
+RM=rm -f
+MV=mv -f
+BOOTSTRAPCFLAGS =
+
+# Project identification -- name, version, and stuff
+
+PROJECTNAME = Booting the Make World System
+PROJECTVERSION = none
+PROJECTLABEL = none
+SETUPLABEL = std
+
+PROJECTCONFIGDIR =
+
+###########################################################################
+# Configuration stuff (jmake, its friends and templates)
+
+JMKMF = jmkmf_used_only_with_installed_utils
+JRESTOREDEPS = $(JMAKESRC)/jrestoredeps
+JMAKE = $(JMAKESRC)/jmake
+JMAKE_DEFINES =
+
+JMAKESRC = $(TOP)/mkworld
+
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) $(BOOT_DEFINES)
+
+###########################################################################
+
+Makefile:: $(JMAKE)
+
+$(JMAKE):
+ @(cd $(JMAKESRC); if [ -f Makefile ]; then \
+ echo "checking $@ in $(JMAKESRC) first..."; $(MAKE) all; else \
+ echo "bootstrapping $@ from Makefile.BOOT in $(JMAKESRC) first..."; \
+ $(MAKE) -f Makefile.BOOT BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \
+ echo "okay, continuing in $(CURRENT_DIR)")
+
+Makefile::
+ -@if [ -f Makefile ]; then \
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(JMAKE_CMD)
+ $(JRESTOREDEPS)
+ @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi
+ @chmod 444 Makefile
+ @echo ==== The new Makefile is for\: ====
+ @$(MAKE) whoami
diff --git a/web/glasgow/lit2x-0.16/literate/PATCHLEVEL b/web/glasgow/lit2x-0.16/literate/PATCHLEVEL
new file mode 100644
index 0000000000..be1dad6619
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/PATCHLEVEL
@@ -0,0 +1 @@
+Glasgow literate programming system, version 0.16, patchlevel 0
diff --git a/web/glasgow/lit2x-0.16/literate/PROJECTS b/web/glasgow/lit2x-0.16/literate/PROJECTS
new file mode 100644
index 0000000000..014d8ec650
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/PROJECTS
@@ -0,0 +1,64 @@
+SIMPLE \defines with parameters
+\begin\end grammar
+better tabulars (changes)
+\owner -- how/where does one such decl apply?
+don't xref uses that are def'd nearby
+tgrind/tags
+do postmakeinfo
+
+de-Birdizing for >#(if|elsif|else|endif)
+
+codethings def'd more than once
+Haskell same-named codethings from diff namespaces
+
+\title as \section0 ?
+
+for large docs, could use
+\reset{indexing,xref}tables to be heaved in periodically.
+
+chg onlyinfo, onlylatex semantics to go straight-through.
+
+onlystandalone, etc.: carry both through, decide on linking
+
+how does CPP interact w/ haskell?
+
+independent code writing / code printing styles.
+
+xtex option?
+
+\begin...\end{invisiblecode}
+
+(info) be able to jump to all places where a function is used
+
+postmakeinfo -- colons in nodenames
+
+index the right things
+
+pagebreaks for code in LaTeX
+
+verbatim in verbatim (cf verbatim.sty)
+
+math mode
+
+and what's this with @'s in codeformat (if the latter exists?!)
+
+multiple indexes -- we need these! (e.g., code for subsystems of a
+larger system don't want to share an index):
+ \index[string]{index-entry-as-usual} % default is "main" index
+ \printindex[string] % default is "main" index
+also
+ \setcurrentindex{string} % to change default
+ \setcurrentcodeindex{string} % where code-ish index-entries go
+Implementation: I'd pre-pend the string to the entry-as-usual
+("string<uniquifier>!"), let LaTeX/makeinfo do the work, then
+post-process to make the separate indexes.
+
+Got a bug with:
+
+ Used only once (ToDo: check ?):
+ <- spaces here
+ >newTyVar :: NFSap TyVar
+
+ditto for \tr{\Haskell}... (defined things)
+
+if lit2pgm fails, nuke the output file (so make will re-try).
diff --git a/web/glasgow/lit2x-0.16/literate/README b/web/glasgow/lit2x-0.16/literate/README
new file mode 100644
index 0000000000..34b9f5af8e
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/README
@@ -0,0 +1,38 @@
+This directory (and its subdirectories) contains version 0.16 of the
+Glasgow literate programming system. This stuff is usually -- but not
+always -- distributed as part of a larger system (e.g., the Glasgow
+Haskell compiler).
+
+The version numbers for this system tend to track those for Glasgow
+Haskell, even if virtually nothing has changed herein. As this system
+is pretty stable, this "version" really has nothing new to offer if
+you have a version 0.06 or 0.09.
+
+The subdirectory "doc" contains the user's guide (notably, the files
+literate.dvi [TeX-produced DVI format] and literate.info [equivalent
+in GNU Info format].
+
+If you are building/installing this stuff as a separate system, please
+consult the relevant section of the user's guide, near the end
+(source: literate/doc/install.lit). If this stuff "came with" another
+system (e.g., GHC or NoFib), simply follow the directions for
+building/installing *that* system.
+
+Once this system is built, if you would like to see its source in
+"literate" form (not overly recommended :-), try:
+
+ % cd <here>
+ % make depend # may be omitted if you've already done it
+ % make lit2stuff.dvi
+ # or...
+ % make lit2stuff.info
+
+The subdirectory "info-utils" contains hacked versions of the GNU
+Info-related utilities, "info" and "makeinfo". See the README file
+there.
+
+Comments about and suggestions for this system would be most welcome.
+You may send them directly to me.
+
+Will Partain
+partain@dcs.glasgow.ac.uk
diff --git a/web/glasgow/lit2x-0.16/literate/TeX-Mathematica-note b/web/glasgow/lit2x-0.16/literate/TeX-Mathematica-note
new file mode 100644
index 0000000000..b597a81ea9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/TeX-Mathematica-note
@@ -0,0 +1,34 @@
+From dan@chem.bu.edu Sat Apr 27 15:20:35 1991
+From: dan@chem.bu.edu (Dan Dill)
+Newsgroups: sci.math.symbolic,comp.text.tex
+Subject: New version of TeX/Mathematica available
+Date: 26 Apr 91 19:30:49 GMT
+Followup-To: sci.math.symbolic
+Organization: Boston University Chemistry Department
+
+A new version (1.3) of TeX/Mathematica is available by anonymous ftp from
+chem.bu.edu (128.197.30.18) in directory /pub/tex-mathematica.
+
+TeX/Mathematica is a set of tools that provide facilities of Mathematica
+Notebooks in a UNIX environment, under GNU Emacs. They permit interaction
+between a text and a Mathematica buffer and, if desired, the use of
+TeX/LaTeX to annotate Mathematica-based explorations and programs. Inclusion
+of Mathematica-generated graphics in TeX/LaTeX documents printed using
+PostScript is supported.
+
+The major new feature is that calculations in a document can automatically be
+encapsulated in Mathematica packages. This means that the document can serve
+both as the description of the package and the source for the package code
+itself, in the spirit of Knuth's WEB system of structured documentation.
+
+With these tools one can interactively develop and refine teaching and
+research documents. The interactive nature of the tools encourages
+Mathematica-based exploration as a natural part of the writing process.
+
+I'd welcome your comments.
+
+Thanks
+
+Dan Dill
+dan@chem.bu.edu
+
diff --git a/web/glasgow/lit2x-0.16/literate/a-cpp-ish-thing-from-the-net b/web/glasgow/lit2x-0.16/literate/a-cpp-ish-thing-from-the-net
new file mode 100644
index 0000000000..41b38e9d5a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/a-cpp-ish-thing-from-the-net
@@ -0,0 +1,257 @@
+From aks@anywhere.ucsb.edu Fri May 3 10:51:57 1991
+From: aks@anywhere.ucsb.edu (Alan Stebbens)
+Newsgroups: comp.lang.perl
+Subject: Program to list (and comprehend) nested includes
+Summary: Program to list nested `cpp' includes
+Keywords: Program lists nested #includes
+Date: 1 May 91 23:57:43 GMT
+Organization: CCSE, Univ. of CA, Santa Barbara
+
+When trying to port software to the IBM RS3000 running AIX 3.1, it
+often occurs that I have to isolate a missing or malformed rerenced to
+some "standard" macro or define. Also, there are many include files in
+the /usr/include hierarchy which are ultimately recursive by
+re-invoking, for example, /usr/include/standards.h. It becomes very
+difficult to understand the dependencies of these include files when
+such recursion occurs is several places or is very deep.
+
+The following program, "includes", is my "quick 'n dirty" solution to
+this problem: it will list, and optionally indent and line-number, the
+standard `cpp' include directives.
+
+Oh yeah, a caveat: I had originally intended the program to be able to
+dynamically interpret #define's and #undef's, but never followed up
+with the code to do the job. Thus, the internal documentation and
+"usage:" show a -D and -U option usage, but don't really do anything
+with it. Perhaps, some other time, I'll make it work as intended. Or,
+someone else will.
+
+Enjoy.
+
+Alan Stebbens <aks@hub.ucsb.edu> (805) 893-3221
+ Center for Computational Sciences and Engineering (CCSE)
+ University of California, Santa Barbara (UCSB)
+ 3111 Engineering I, Santa Barbara, CA 93106
+
+============================= cut here ===================================
+#!/bin/perl
+# includes [[-[vincu]...] [-Idir] [-Dname] [-Uname]]... files
+#
+# Given a list of files, determine the #include dependency list
+# given '-c', use CPP to determine the _dynamic_ dependency list,
+# otherwise, the static include file dependency list is produced.
+#
+# If the `-D' or `-U' options are given, `-c' is assumed.
+#
+#
+$IndentStr = ' ' x 4;
+@IncludeDirs = ('.');
+@Defines = ();
+$Verbose = 0;
+$Pathnames = 0;
+$LineNums = 0;
+$Indent = 0;
+$SortUniq = 0;
+&Usage unless $#ARGV >= $[;
+while ($_ = shift) { # scan arguments
+ if (!/^-/) {
+ unshift(@ARGV,$_);
+ last;
+ }
+ while (s/^-(.)/-/) {
+ $Compile++ if $1 eq 'c';
+ $Indent++ if $1 eq 'i';
+ $LineNums++ if $1 eq 'n';
+ $Pathnames++ if $1 eq 'p';
+ $SortUniq++ if $1 eq 's';
+ $Verbose++ if $1 eq 'v';
+ if ($1 =~ /[IDU]/) {
+ $opt = $1;
+ s/^-(.*)/-$opt$1/; # put option back in
+ push(@IncludeDirs,$_) if $opt eq 'I';
+ push(@Defines,$_) if $opt =~ /DU/;
+ last;
+ }
+ &Usage unless $1 =~ /[cinpsv]/;
+ }
+}
+&Usage if $SortUniq && ($LineNums || $Indent);
+$Compile++ if $#Defines >= $[; # any defines? compile it
+$Pathnames = $LineNums = $Indent = 1 if $Verbose;
+@Files = @ARGV;
+while ($File = shift(@Files)) {
+ printf "%s:\n",$File;
+ if ($SortUniq) {
+ select(STDOUT); $| = 1;
+ open(SORT,"|sort -u +1 -2") || die "Can't open pipe to `sort -u' filter because $!\n";
+ select(SORT); $| = 1;
+ }
+ &ShowIncludes($File,0);
+ if ($SortUniq) {
+ close(SORT);
+ select(STDOUT);
+ }
+}
+exit;
+
+%Included = ();
+sub ShowIncludes {
+ local($name,$level) = @_;
+ local(*FILE);
+ local($_,$.);
+ local($pathname,$lq,$incname,$rq);
+ local($indent) = $Indent ? $IndentStr x $level : '';
+
+ if (open(FILE,$name)) {
+ $Included{$name}++;
+ while (<FILE>) {
+ next unless /^#include/;
+ chop;
+ if (/^#include\s*(")([^"]*)(")/ ||
+ /^#include\s*(<)([^>]*)(>)/) {
+ ($lq,$incname,$rq) = ($1,$2,$3);
+ print $indent;
+ printf "%3d:",$. if $LineNums;
+ printf "#include %s%s%s",$lq,$incname,$rq;
+ if ($file = &FindFile($incname,($lq eq '"'))) {
+ printf "\t(%s)",$file if $Pathnames;
+ print "\n";
+ &ShowIncludes($file,$level+1) unless $Included{$file};
+ } else {
+ printf ": can't find $incname\n";
+ }
+ } else {
+ print ": bad syntax.\n";
+ }
+ }
+ close FILE;
+ } else {
+ print ": can't open $name because $!\n";
+ }
+}
+
+sub FindFile {
+ local($file,$localflag) = @_;
+ local($path);
+ if ($localflag) {
+ foreach $dir (@IncludeDirs) {
+ ($path = $dir . '/' . $file) =~ s/^-I//;
+ return $path if -f $path;
+ }
+ }
+ foreach $dir ('/usr/local/include', '/usr/include') {
+ return $path if -f ($path = $dir . '/' . $file);
+ }
+ '';
+}
+
+sub Usage {
+ select(STDERR);
+ print STDERR <<"EOF";
+usage: includes [-cinspv] [-Ipath]... [-[D|U]name]... files
+Prints the '#include' statements referenced by the named files, automatically
+following nested #includes; statically recursive #includes are detected.
+ -c Compile (interpret) #ifdef's and expressions
+ -i Indent nested #includes
+ -n Print the line numbers of the #include statements
+ -p Print the absolute path names for each include file
+ -s Run the #includes through a `sort -u' filter
+ -v Verbose mode; implies `-inp' options
+ -Ipath Add `path' to the include search path.
+ -Dname Define `name'; implies the `-c' option.
+ -Uname Undefine `name'; implies the `-c' option.
+Sorting is mutually exclusive with indents and line numbering.
+EOF
+ exit 1;
+}
+
+============================= cut here ===================================
+--
+
+Alan Stebbens
+
+From aks@anywhere.ucsb.edu Fri May 3 10:52:08 1991
+From: aks@anywhere.ucsb.edu (Alan Stebbens)
+Newsgroups: comp.lang.perl
+Subject: Program to check for balanced #{if|else|endif}s
+Summary: List, with optional line numbers and indention, `cpp' conditionals
+Keywords: CPP #ifdef #else #endif listing
+Date: 1 May 91 23:47:36 GMT
+Organization: CCSE, Univ. of CA, Santa Barbara
+
+The following is a perl program to list, with optional indentions
+and line numbers, the `cpp' conditionals: #ifdef, #elif, #else, #endif.
+I wrote this because I was unsuccessfully trying to find a missing
+#ifdef in some newly patched software.
+
+Enjoy.
+
+Alan Stebbens <aks@hub.ucsb.edu> (805) 893-3221
+ Center for Computational Sciences and Engineering (CCSE)
+ University of California, Santa Barbara (UCSB)
+ 3111 Engineering I, Santa Barbara, CA 93106
+
+============================= cut here ===================================
+#!/bin/perl
+# ifdefs [-n] [-i INDENT] [-l]
+require 'getopts.pl';
+
+&Getopts('i:nl') || die "Usage: ifdefs [-i indent] [-l] [-n] [files...]\n";
+
+$INDENT = $opt_i ? $opt_i : 3;
+$indent = 0;
+@block = ();
+@state = (0);
+# States: 0 - nothing; 1 = #if ; 2 = #elsif ; 3 = #else
+select(STDOUT); $| = 1;
+while (<>) {
+ if (/^#\s*(if|ifn?def|elif|elsif|elseif|else|endif)/) {
+ $key = $1;
+ s/[ \t]+/ /g;
+ $nextindent = $indent;
+ if ($key eq 'if' || $key =~ /ifn?def/) {
+ $state[$indent] = 1;
+ $block[$indent] = "$key $.";
+ $state[++$nextindent] = 0;
+ } elsif ($key eq 'elseif' || $key eq 'elsif' || $key eq 'elif') {
+ $indent--;
+ &Error if !$indent || $state[$indent] < 1 || $state[$indent] > 2;
+ $block[$indent] = "$key $.";
+ $state[$indent] = 2;
+ } elsif ($key eq 'else') {
+ &Error if !$indent;
+ $indent--;
+ &Error if $state[$indent] < 1 || $state[$indent] > 2;
+ $state[$indent] = 3;
+ $block[$indent] = "$key $.";
+ } elsif ($key eq 'endif') {
+ &Error if !$indent || $state[$indent];
+ $indent--;
+ &Error if !$state[$indent];
+ $state[$indent] = 0;
+ $block[$indent] = '';
+ $nextindent--;
+ }
+ } else {
+ next unless $opt_l;
+ }
+ printf "%4d:",$. if $opt_n;
+ printf "%s%s",(' 'x($indent * $INDENT)),$_;
+ $indent = $nextindent;
+}
+
+sub Error {
+ if (!$indent) {
+ printf "ERROR: Unmatched \#%s:\n%4d: %s",$key,$.,$_;
+ } else {
+ printf "ERROR: Out of place \#%s:\n%4d: %s",$key,$.,$_;
+ ($keyw,$keyl) = split(' ',$block[$indent]);
+ printf "Previous \#%s at line %d not terminated\n",$keyw,+$keyl;
+ }
+ next;
+}
+============================= cut here ===================================
+--
+
+Alan Stebbens
+
diff --git a/web/glasgow/lit2x-0.16/literate/code-bug.tex b/web/glasgow/lit2x-0.16/literate/code-bug.tex
new file mode 100644
index 0000000000..7007b2b8ee
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/code-bug.tex
@@ -0,0 +1,50 @@
+\documentstyle[11pt,code]{article}
+\begin{document}
+
+\section{Section 1}
+
+Here is a non-first paragraph of code.
+
+\begin{code}
+f x y = x
+g x y = x
+f1 x y = x
+g1 x y = x\end{code}
+
+Here is the same thing with some index entries immediately following.
+
+\begin{code}
+f x y = x
+g x y = x
+f1 x y = x
+g1 x y = x\end{code}
+\index{foo}%
+\index{bar}%
+\index{baz}
+
+{\em The bug is the overly-big space above this line.}
+
+\section{Section 2}
+
+Now we do the same thing, but with `quotation' (another `list'
+environment), not `code'.
+
+\begin{quotation}
+f x y = x
+g x y = x
+f1 x y = x
+g1 x y = x\end{quotation}
+
+Here is the same thing with some index entries immediately following.
+
+\begin{quotation}
+f x y = x
+g x y = x
+f1 x y = x
+g1 x y = x\end{quotation}
+\index{foo}%
+\index{bar}%
+\index{baz}
+
+And some final text for this section.
+\end{document}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/Jmakefile b/web/glasgow/lit2x-0.16/literate/doc/Jmakefile
new file mode 100644
index 0000000000..aeb058e04a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/Jmakefile
@@ -0,0 +1,8 @@
+LitStuffNeededHere(docs depend)
+InfoStuffNeededHere(docs)
+
+LitSuffixRule(.lit,)
+
+LitDocRootTarget(literate,lit)
+
+InstallInfoFileTarget(literate,literate,$(INSTINFODIR))
diff --git a/web/glasgow/lit2x-0.16/literate/doc/REM.comments b/web/glasgow/lit2x-0.16/literate/doc/REM.comments
new file mode 100644
index 0000000000..bab856a835
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/REM.comments
@@ -0,0 +1,239 @@
+From REM@suwatson.stanford.edu Mon Jul 8 09:29:34 1991
+X-VM-Attributes: [nil nil nil nil t]
+Status: RO
+Via: uk.ac.nsf; Mon, 8 Jul 91 09:29:08 BST
+Received: from vax.nsfnet-relay.ac.uk by sun2.nsfnet-relay.ac.uk
+ with SMTP inbound id <5497-0@sun2.nsfnet-relay.ac.uk>;
+ Sun, 7 Jul 1991 16:34:38 +0100
+Received: from [36.21.0.12] by vax.NSFnet-Relay.AC.UK via NSFnet with SMTP
+ id aa03596; 7 Jul 91 16:16 BST
+Received: from SUWATSON.stanford.edu
+ by SUWATSON.stanford.edu (IBM VM SMTP R1.2.2MX) with BSMTP id 6616;
+ Sun, 07 Jul 91 08:30:53 PDT
+From: REM@SUWATSON.stanford.edu
+Sender: REM@suwatson.stanford.edu
+To: partain
+Subject: Glasgow literate programming (documentation -- long)
+Date: Sun, 07 Jul 91 08:30:50 PDT
+
+(Hi. I'm currently months behind in reading PARA archives, but now trying
+to catch up. Currently I'm reading postings from 1991.Apr ...)
+
+<<Date: Tue, 23 Apr 91 13:59:41 BST -- Programs are just documents for
+people to read and enjoy which happen to have machine-manipulable code
+"buried" in them.>>
+
+Hmmm, interesting concept. So you just write as if you were submitting an
+article to COMM ACM with embedded program snippets, except (1) there's
+automatic machinery to extract the snippets, and (2) all the snippets
+together in your article just happen to be one complete program when put
+together!
+
+<<... depending on whether that language is "supported" or not.>>
+I hope you support LISP.
+
+<<programs/documents divided into sections, subsections within sections,
+subsubsections...>>
+
+Whether this is a good idea or not is a major question. If you have one
+person organizing the file and others just add to pieces, and if it's
+small enough that others can find the appropriate place easily, this
+might work. This assumes everyone can agree on the organization. But a
+non-heirarchial representation, nodes with links but no strict heirarchy,
+or even pure tagged-node representation, is usually necessary when more
+than one person can contribute new nodes asynchronously and without
+agreeing upon a heirarchy that the new nodes can neatly fit into. The
+best model may be to simply have each section tagged with keywords, and
+have tools for searching for the desired section by keywords, and let
+anyone try to make a heirarchial index of the whole document for their
+personal use if they feel they can but watch them give up in frustration
+as they have more and more trouble fitting new nodes into their old
+heirarchy.
+
+<<Hierarchy is a very powerful structuring tool, but its utility for
+wading around a large sea of code is not apparent.>>
+
+Yes. That's the other problem with a heirarchy. Even if you can neatly
+organize everything into topics subtopics etc., can you find things
+easily by traversing that heirarchy, or do you really need keywords after
+all just so you can quickly find a given node by name (keyword) instead
+of by location (topic subtopic etc.).
+
+<<Say you're writing a Haskell compiler ...>>
+As in Eddie Haskell on Leave It To Beaver??
+
+<<You could make copies of files, edit them, etc., but that's tacky,>>
+
+not to mention impossible to maintain, and a royal pain even if you can.
+You really want HyperText, any segment of text can be located in multiple
+places simultaneously and all edits immediately propagate, because really
+each occurance of the piece of text is via pointer to one master copy.
+But making HyperText work in the first place, then arranging for
+incremental backups and rollbacks etc. is really hard. I wonder if the
+Xanadu folks have found real solutions for these major problems, or are
+just winging it (sweeping the dirt under the rug and hoping nobody will
+notice)?
+
+<<As it stands, this system lets you put "\begin{onlystandalone}" and
+"\end{onlystandalone}" around pieces of your files that only apply in the
+"do this as a standalone document" case; similarly,
+"\begin{onlypartofdoc}" and "\end{onlypartofdoc}" for stuff that only
+applies in the "the glorious whole" case.>>
+
+UUGGGGLLLLEEEEEEEE! You've re-invented conditional assembly, a common
+feature of machine-language assemblers for at least 20 years. Even
+CommonLisp has it, but I avoid it since it can so easily get out of hand.
+But as things stands, if you don't have HyperText, then conditional
+assembly is probably the only game in town for having multiple versions
+of a document simultaneously available in the same file.
+
+One problem, you can't have the different versions put the sections in a
+different sequence, unless you use the most hated feature ever invented,
+CONDITIONAL-ASSEMBLY GOTO, present in IBM 360 assemblers I believe. But
+what the heck, if you want your document to look like a BASIC program,
+it's your priviledge.
+
+Hmmm, about assembly macros? IBM 360 assembler has them too, and they are
+a bit cleaner than GOTOs. Each section you might want to put in various
+places, you define as a macro at the top of the file, then simply call it
+where you want that body of text to appear in the virtual document that
+exists under any of the presentation modes. Unfortunately that means if
+you look at the raw source file, the top of the file has all these random
+sections, instead of any sort of introduction, because macros have to be
+defined before used. There are various hacks to avoid this problem...
+
+<<We don't have a "\define" command that let's you define new macros in
+terms of old ones.>>
+Awwww, shucks.
+
+<<Some programming languages have a narrow-minded idea about what order
+the pieces of a program must be presented (e.g., COBOL: identification
+division, then file division, then data division>>
+
+I did, sort of. I knew the divisions but not what order they were
+supposed to be in, but I knew they had to be in the right order and I'd
+look in the manual or at a sample program if I ever needed that info.
+(Last time I touched COBOL was 1974, but I respect it for having some
+good ideas not present in any other language I've ever seen,
+particularily single declaration of relationship between variables in
+records in memory and columns of data in file, even if braindamaged by
+fixed-width mentality. I wish that single-declaration method of defining
+I/O syntaxes existed in other languages that allowed variable-length
+fields. printf and scanf are a poor attempt.)
+
+<<Within non-code parts of documents, code snippets may be included
+between `at' signs; e.g., "@f x y = y@">>
+
+I don't like that. What if your code contains an atsign to indicate
+indirect addressing through a pointer variable? Do you double the atsign,
+or put a backslant before it?
+
+A better way is an invention I made when writing POX (Prototype Overlay
+Xerographics) at SU-AI (Sail.Stanford.Edu under the domain system),
+namely having a whole class of available parenthesizing (grouping)
+characters, some symmetric like '' and "" and @@ and // and \\ and some
+balanced like () and {} and [] and <> and /* */. You can use any pair
+from either class to avoid stepping on the same character within the
+embedded text. Furthermore you can nest any of the balanced ones (you
+can't nest the symmetric ones for obvious reasons).
+
+In POX, stuff inside a single level of generic-parentheses was treated as
+a body of whatever (macro definition etc.) but was further interpreted,
+whereas inside a second level of balanced generic-parentheses was
+super-quoted, but for your application of quoting code segments from
+within text this distinction may be moot, but I mentionned it to make my
+presentation of my invention complete.
+
+(I had a further idea of allowing interchangeability between
+generic-parentheses and BEGIN-END pairs which can be named. For very long
+quoted passages, finding the matching ( and ) can be very painful,
+whereas if you say BEGIN "Comments on sex" and later say END "Comments on
+sex" but you don't have your parentheses or BEGIN-END pairs matched, the
+compiler will notice the problem and help you diagnose it. So you
+normally use parentheses for short passages where you can eyeball the
+matching or EMACS etc. can flash the cursor back and forth to help you,
+but you use named BEGIN-END pairs over large blocks where you need
+additional help. But I never had time to program this BEGIN-END extension
+to parenthesization. P.s. the original labeled BEGIN and END is from
+SAIL, a variant of ALGOL 60 developed at SU-AI, the Stanford University
+Artificial Intelligence Lab; P.S., from those 5 initial letters, drop the
+U to get SAIL, drop the L to get SU-AI.)
+
+<<"\tr{<text>}" command; the only restriction on "<text>" is that braces
+must be balanced.>>
+
+They should use the POX convention. If you use \tr{<text>} then of course
+the braces must be balanced in <text>, but if you want to quote text that
+has unbalanced braces you use some other nesting pair such as \tr[<text>]
+or \tr/*<text>*/} etc. to avoid stepping on some unbalanced character. Of
+course if you want to quote the ASCII character set, but omit all the
+right-sides of each nesting pair, you are up a creek, since no matter
+what nesting pair you use on the outside you get an inbalance from the
+<text>, but c'est la vie.
+
+<<No graphics, pictures, or sound.>>
+Someday maybe we'll all be using the NBS standard for representing
+structured multimedia text, then you'll be able to include sound etc. :-)
+
+<<it's *your problem* to make sure that you don't get nodename clashes.>>
+
+If somebody proposes a new nodename, your system should tell him if it is
+already in use, and also tell which similar nodenames (say varying by at
+most two characters replaced or inserted or deleted) are also in use, to
+help him find a name that not only isn't in use but isn't so close to
+something in use as to encourage typos to collide with another name.
+
+<<Having one index for a pretty-big program is a dubious proposition; you
+get a *huge* index.>>
+
+I prefer one big index so I can find what I want instantly even if I
+don't know a priori its syntactic class (the Common Lisp book has this
+single-index feature) rather than having to first find the correct index
+before I can find what I want. Perhaps you should do like Macintosh menus
+sort of. In your case, you select a mode and an index term. It shows you
+the vicinity of that index term in the full index, but all words not in
+the correct mode are dimmed (grayed). So you can still see the words from
+the other parts of the index, but you can easily skip over them as you
+eyeball the index. (If you use this idea, please give me credit. I
+invented it as I was replying to your posting tonight, or is it morning
+already, I see sunlight behind the window curtains, sigh, up too late.)
+
+<<The main thing that is a pain about the current sectioning (see section
+*Note Sectioning::) is making up unique node names all the time.>>
+
+I agree. Nobody should be REQUIRED to do that in the course of entering
+new text (I hate having to remember to press RETURN every 70 or so
+characters too, which is why I use miniWRITER all the time for entering
+text, because it has automatic word wrap). There should be a single
+keystroke that generates a new label with some obvious machine-look such
+as LISP's GENSYM feature that makes G0001 G0002 G0003 etc. It should of
+course skip over any that already exist. Later you should be able in
+reviewing the document to notice one of these and decide you'd like to
+change it to a more meaningful label, get help finding one that doesn't
+step on existing ones or get too close (see earlier), and upon finding
+one ask the program to automatically change the definition and all
+references to this label. If you want to do a massive cleanup some day,
+there should be a command to search to find the next such
+machine-generated label.
+
+<<* recording-who-to-blame:: \owner{<name>}.>>
+
+Hmmm, sounds like an audit trail, very important in any commercial
+venture when more than one person can modify the file. You absolutely
+have to an audit trail of who made what changes or one worker can
+sabotage the project and blame it on the other and nobody can prove
+anything.
+
+No, I see you mean something different, sigh. Well, if somebody can mark
+a section as being his, and the program respects that claim (as in gold
+mining) and won't anyone else modify that section, only attach proposed
+changes to it, but the author must approve those proposals before the
+section can be destructively changed, that would be a good method of
+audit control. You'd need a way that one person can "give" a section to
+another, and that person can accept or refuse the gift, all
+program-mediated.
+
+<<[Para: CHOPPED OFF HERE -- another 60K or so to go]>>
+Gosh darn. How can I get the rest of it so I can nitpick it??
+
+
diff --git a/web/glasgow/lit2x-0.16/literate/doc/april91.lit b/web/glasgow/lit2x-0.16/literate/doc/april91.lit
new file mode 100644
index 0000000000..0fa0bea742
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/april91.lit
@@ -0,0 +1,572 @@
+\section[april91-proposals]{APRIL91 PROPOSALS}
+
+%************************************************************************
+%* *
+\subsection[april91-new-ideas]{New ideas}
+%* *
+%************************************************************************
+
+These ideas have piled up over the past six months. NONE OF THEM ARE
+IMPLEMENTED. And some are TINY little things (and some are BIG).
+
+JULY91: I have fleshed out the \sectionref{literate-para-mode} and
+\sectionref{lit2lit} comments, as these directions piqued the interest
+of some fellow GRASPers.
+
+%************************************************************************
+%* *
+\subsubsection[delatexify-commands]{Make the commands look less like \LaTeX{}}
+%* *
+%************************************************************************
+
+The biggest practical problem that has arisen among the (few) users of
+the literate programming stuff is that they think they're writing
+\LaTeX{} files and are surprised/disappointed when \LaTeX{} fails to
+grok their files. We have been too successful in making the notation
+``\LaTeX{}-like!''
+
+One way to make the notation less \LaTeX{}-like while maintaining the
+notation's familiarity is to switch to mixed-case names, used in a
+consistent manner; for example:
+\begin{verbatim}
+CURRENTLY WOULD BECOME ...
+\documentstyle \documentStyle
+\printindex \printIndex
+\begin{flushleft} \begin{flushLeft}
+\end{verbatim}
+Command/environment names that are one word (e.g.,
+\tr{\begin{enumerate}}) would be unchanged.
+
+Alternatively, we could make the literate-system case-insensitive
+where command names are concerned and merely make it our {\em
+convention} to use mixed-case names.
+
+%************************************************************************
+%* *
+\subsubsection[multiple-indexes]{Multiple indexes}
+%* *
+%************************************************************************
+
+Having one index for a pretty-big program is a dubious proposition;
+you get a {\em huge} index. I think you need multiple indexes---in
+the case of a compiler, you might then have a separate index for:
+parser, typechecker, syntactic desugarer, optimiser, etc.
+
+Let's assume you index all the pieces of a compiler (as above) as
+self-contained units. PROBLEM: it is the uses of functions, etc.,
+that {\em cross} such boundaries that you would MOST like to have your
+attention drawn to.
+
+That problem aside, I think this is the basic solution:
+\begin{description}
+\item[\pl{\defineindex{<index-tag-string>}}:]
+Says that \pl{<index-tag-string>} is ``legal'' hereafter.
+Requiring/encouraging these \tr{\defineindex} will help to catch typos.
+
+\item[\pl{\index[<index-tag-string>]{<entry>}}:]
+The \tr{\index} command has an optional \pl{<index-tag-string>} with
+which this \pl{<entry>} should be tagged. The default tag
+string is \tr{main} (unless reset with \tr{\setindex...}; below).
+
+\item[\pl{\printindex[<index-tag-strings>]}:]
+Print an index here, made up from all the entries that have one of the
+\pl{<index-tag-strings>}. The default tag string is (same
+caveats...) \tr{main}.
+
+\item[\pl{\setcurrentindex{<index-tag-string>}}:]
+Set the default tag string for \tr{\index} commands in text.
+\end{description}
+
+I think you could use the mechanism above to come close to Texinfo's
+idea about multiple indexes.
+
+%************************************************************************
+%* *
+\subsubsection[better-Haskell-indexing]{Better \Haskell{} indexing}
+%* *
+%************************************************************************
+
+(The idea probably carries over to other languages.) Stick the whole
+literate-program \Haskell{} source into an ``interesting-thing
+finder'' (call it \tr{htags} :-), getting back (source-location,
+index-entry) pairs. Then the only trick is to tack each index-entry
+onto the code block nearest to the reported source-location.
+
+%************************************************************************
+%* *
+\subsubsection[revised-sectioning]{Revisions to the sectioning commands}
+%* *
+%************************************************************************
+
+The main thing that is a pain about the current sectioning (see
+\sectionref{Sectioning}) is making up unique node names all the time.
+I propose the following ``system'' for the optional arg to
+\tr{\section<n>}; shown by example:
+\begin{description}
+\item[\pl{\section{<title>}}:]
+(As currently.) A default node name, made from the section number.
+No \tr{\label} created.
+
+\item[\pl{\section[]{<title>}}:]
+No node name, no node, no \tr{\label}. Not recommended :-)
+
+\item[\pl{\section[<the-usual>]{<title>}}:]
+(As currently.) Arguably, the stuff to let you specific next/prev/up
+explicitly should be dropped (to partly de-Info-ise the notation).
+
+\item[\pl{\section["]{<title>}}:]
+(The new one.) The node name should be the same as the \pl{<title>}
+(``ditto''). No \tr{\label} would be generated. Some massaging would
+be required to remove nodename-hostile characters from the title
+(e.g., colons).
+\end{description}
+
+%************************************************************************
+%* *
+\subsubsection[BNF-grammars]{A ``BNF grammar'' environment}
+%* *
+%************************************************************************
+
+This would work like the \tr{verbatim} program used with the
+\Haskell{} report; you could say:
+\begin{verbatim}
+\begin{grammar}
+exp -> aexp
+ | exp aexp
+ | exp_1 op exp_2
+ | @-@ aexp
+ | @\@ apat_1 ... apat_n [gd] @->@ exp
+ | @if@ exp_1 @then@ exp_2 @else@ exp_3
+ | exp @where@ @{@ decls @}@
+ | @case@ exp @of@ @{@ alts @}@
+ | exp @::@ [context @=>@] atype
+\end{grammar}
+\end{verbatim}
+and respectable BNF-looking stuff would appear in your output. Index
+entries for the definitions of nonterminals would be generated;
+possibly a \tr{[noindex]} option to suppress that.
+
+I'd also like to do something for inference rules, but I'm fairly
+baffled about what that might be. (They can be mightily complicated,
+and it's not clear that a plain-ASCII form is possible.)
+
+%************************************************************************
+%* *
+\subsubsection[pseudo-C-preprocessor]{Fake ``C pre-processing''}
+%* *
+%************************************************************************
+
+Change things so that literate documents are first put through a
+``fake C pre-processor'' (this section assumes you know what a C
+pre-processor does). Notes:
+\begin{enumerate}
+\item
+The relevant commands would start with \tr{##} (to avoid confusion w/
+the real thing); hence, \tr{##if}, \tr{##endif}, \tr{##define},
+\tr{##include}, etc.
+
+\item
+(Very important.) This pseudo-C-preprocessor does NOTHING inside:
+\begin{itemize}
+\item
+Code environments (and the Bird-track equivalent).
+\item
+Verbatim environments.
+\item
+\tr{\tr} and \tr{\pl} commands (and any friends they may have).
+\item
+\tr{rawlatex} environments (next section).
+\end{itemize}
+
+\item
+All of the current dubious \tr{only<this-or-that>} environments and so
+on would go away; what you currently write as:
+\begin{verbatim}
+ \begin{onlystandalone}
+ \documentstyle[11pt,literate]{article}
+ \begin{document}
+ \title{Glasgow Literate Programming\\ User's Guide}
+ \date{April 1991}
+ \maketitle
+ \begin{onlylatex}
+ \tableofcontents
+ \end{onlylatex}
+ \clearpage
+ \end{onlystandalone}
+\end{verbatim}
+would be re-written as:
+\begin{verbatim}
+ ##if defined(STANDALONE)
+ \documentstyle[11pt,literate]{article}
+ \begin{document}
+ \title{Glasgow Literate Programming\\ User's Guide}
+ \date{April 1991}
+ \maketitle
+ ##if defined(MK_LATEX)
+ \tableofcontents
+ ##endif /* MK_LATEX */
+ \clearpage
+ ##endif /* STANDALONE */
+\end{verbatim}
+
+\item
+\tr{##include} would take the place of the current bogosity
+\tr{\inputnow}.
+
+\item
+\tr{##define} would take over from the current emasculated
+\tr{\define} and would emphasise the point that this literate notation
+is a fixed notation, lacking general macros.
+
+\item
+Running this or that program would pre-\pl{##define} certain symbols
+(e.g., \pl{MK_LATEX}), but I don't know exactly which just yet.
+
+\item
+Using \pl{##defines} and \pl{##ifdef}'ing easily generalises the
+``standalone/partofdoc'' dichotomy (which badly needs generalising).
+\end{enumerate}
+
+%************************************************************************
+%* *
+\subsubsection[invisible-code]{Invisible code}
+%* *
+%************************************************************************
+
+I am wondering if we shouldn't have a code environment of the form:
+\begin{verbatim}
+\begin{invisiblecode}
+main (int argc, char **argv)
+{
+ printf("Hello, Seaworld!\n");
+}
+\end{invisiblecode}
+\end{verbatim}
+for code that {\em should} be extracted (\tr{lit2pgm}) but that {\em
+should not} be displayed in \tr{lit2latex/lit2texi} documents.
+This would probably be used when you want to include most, but not all,
+of a program's code---in a paper for publication, for example.
+
+My only fear is that it is too easily subject to abuse.
+
+Perhaps the C-pre-processing stuff is a better idea...
+(\sectionref{pseudo-C-preprocessor}).
+
+%************************************************************************
+%* *
+\subsubsection[text-in-code]{Plain text in your code}
+%* *
+%************************************************************************
+
+In Knuth's WEB, you can refer to code-things in the text parts of the
+document/program {\em and} to text-things in your code. (As I recall,
+putting \tr{|} around text switches it to
+whatever-you're-not-doing-now (code or text)).
+
+We have the first (the \tr{@...@} shorthand to refer to code things
+while in text), but not the second: what's in a code environment is
+code just like you would see in an illiterate program in the same
+language.
+
+I guess the right solution is to have specially-marked comments
+(again, language-dependent) that say, ``Don't treat this as just a
+comment in this programming language, but extract it and
+mangle/massage it as if it were literate-document text.''
+
+A pain to implement. Not worth it?
+
+%************************************************************************
+%* *
+\subsubsection[diff-fonts-in-text]{Using many ``fonts'' in text}
+%* *
+%************************************************************************
+
+I find the \tr{\tr} (``typewriter font'') and \tr{\pl} (``plain
+font'') commands quite useful. (Yes, I know they go against the
+intensional markup principle (\sectionref{ASCII-declarative-markup}),
+but they are {\em so} convenient...)
+
+I'm inclined to make up notations for italics, small caps, and bold
+(and their ASCII-only ``equivalents'') and then try to systematize
+their use. Hmmm....
+
+I've found the Texinfo attempt to have a command for every different
+kind of thing you might want to talk about in a document to be too
+much and also unsatisfying.
+
+%************************************************************************
+%* *
+\subsubsection[code-in-text-formatting]{Formatting code-ish things in text}
+%* *
+%************************************************************************
+
+Right now, the \tr{@...@} shortcut notation means: Format this and
+automagically index it as for the code parts of the document.
+
+Strictly speaking then, I think the \tr{@...@} notation should only be
+used to refer to things that {\em actually exist} in the code parts of
+the document, and {\em not} for code snippets, fragments, and other
+things mentioned along the way.
+
+For this latter task, perhaps a \tr{\code[<language>]{<text>}} command
+is in order. This says: format this \pl{<text>} as for
+\pl{<language>}, but don't index it or pretend that it actually has
+anything to do with the real code in the program.
+
+%************************************************************************
+%* *
+\subsubsection[interface-with-papers]{Interface with plain \LaTeX{} papers}
+%* *
+%************************************************************************
+
+At least in our setting, it is likely we've written one or more papers
+about some interesting part of the literate program we're writing.
+The paper is likely to be:
+\begin{itemize}
+\item
+relatively polished (so you'd like to re-use that effort);
+\item
+either a decent introduction to some part of the program, or a
+succinct synopsis of some part;
+\item
+in straight \LaTeX{}, but using features quite beyond our literate
+markup, and including figures, etc.;
+\item
+not to be changed in any way.
+\end{itemize}
+
+At the least, I'd like to be able to include the paper in toto, and
+have pointers into it (refs to its labels).
+
+More/better ideas welcome.
+
+%************************************************************************
+%* *
+\subsubsection[literate-para-mode]{A literate Para mode}
+%* *
+%************************************************************************
+
+[See also \sectionref{lit2lit}.]
+
+The sad fact is that, at the moment, these literate programs/documents
+are typed in as just plain files and manipulated as such. They are
+only processed into LaTeX/Info documents after the fact (and only
+occasionally).
+
+Para mode is a GNU emacs mode that (roughly...) lets you both edit
+Texinfo files {\em and} jump around in them like Info files, based on
+the node structure. Either edit-as-normal or navigate-as-Info.
+
+I think there are possibilities for doing the same thing with these
+literate documents/programs. Then you'd get the benefits of
+navigation, following indexery, etc., {\em as you create the files}.
+
+One major problem (?): the literate sectioning makes it quite easy to
+navigate {\em within} a file, but, for it to be worth it, you'd like
+the ``literate Para mode'' (in navigation mode) to be able to carry
+you to the right place when you, e.g., want to go ``up'' from the
+first \tr{\section} in a file.
+
+Implementation: my first cut would be: run something over all the
+literate files in a program to collect ``Para-useful'' information;
+save this somewhere---this is the moral equivalent of a TAGS file.
+Then the navigation commands, etc., would use the pseudo-TAGS info to
+do their thing. Because the info would get out of date as you hack on
+your program, you'd re-make the pseudo-TAGS stuff whenever you stepped
+out for coffee, lunch, or sleep.
+
+%************************************************************************
+%* *
+\subsubsection[lit2lit]{A \tr{lit2lit} program (to help implement a Para system)}
+%* *
+%************************************************************************
+
+[This might be a better way to implement a literate Para ...] Have a
+program that takes a set of \tr{.lit} files, munges them to do all the
+usual cross-referencing, etc., etc., and then writes out {\em versions
+of the original files} with all the linking info, etc., etc., inserted
+as {\em comments}. Call the program \tr{lit2lit}...
+
+If you took the \tr{lit2lit} output and re-ran it through one of the
+other programs, e.g., \tr{lit2latex}, it would produce {\em exactly}
+the same output.
+
+The purpose of the information stored in comments would be to provide an
+Emacs mode (or something) enough information to help you jump around
+in a large program or generally do useful stuff.
+
+For example, it might insert links and things for something like Bob
+Weiner's Hyperbole system.
+
+I'm thinking that \tr{lit2lit} would be re-run over a system's sources
+every night by \tr{cron(1)}.
+
+%************************************************************************
+%* *
+\subsubsection[xtex-options]{Generating \LaTeX{} documents especially for \tr{xtex}}
+%* *
+%************************************************************************
+
+\tr{Xtex} is a (free) DVI previewer with some hypertext-ish features;
+in particular, if you click on a reference to a label, then it takes
+you to the page where that label is defined. By generating a
+``\LaTeX{}'' document with all the linking info explicit (in the form
+of labels and references to them), \tr{xtex} would do almost all the
+jumping-around stuff that \tr{info} and \tr{xinfo} do for you. {\em
+And you don't lose the font information.}
+
+%************************************************************************
+%* *
+\subsubsection[free-text-index]{A free-text ``index''}
+%* *
+%************************************************************************
+
+OK, even with all the automagical indexing, cross-referencing, etc.,
+occasions will arise when you say, ``Help! I need to look absolutely
+everywhere for \pl{<foo>}!'' (Like you do with grep/tags, but
+preferably nicer---all the tricks of the free-text indexing trade.)
+
+It would be great to have a ``free text index'' button or pseudo-node
+(an Info ``node'' that, when you jump to it, puts you in a
+free-text-search mode. Of course, the free-text-search should be able
+to plunk you down in the Info node you finally select).
+
+I really don't want to implement this myself :-)
+
+%************************************************************************
+%* *
+\subsubsection[magic-Info-nodes]{Other ``magic'' Info nodes...}
+%* *
+%************************************************************************
+
+The ``free text index'' magic Info node makes me wish for {\em other}
+nodes-that-do-weird-things when you jump to them... You jump to it
+and... it starts up a PostScript previewer and shows me a picture...
+or sound... or my text editor so I can send a gripe to the maintainer
+of \pl{foo}... and so on.
+
+%************************************************************************
+%* *
+\subsubsection[revised-pgm-options]{Revise the way options are fed to \tr{lit2*} programs}
+%* *
+%************************************************************************
+
+Using getopt(3)-style one-letter options is getting messy---there are
+too many of them. Perhaps time for something more complicated...
+
+%************************************************************************
+%* *
+\subsubsection[mixing-Bird-code-and-other]{Mixing code in ``Bird tracks'' with other code}
+%* *
+%************************************************************************
+
+When you put something in a code environment, e.g.,
+\begin{verbatim}
+\begin{code}
+main _ = [ AppendChan stdout "Hi, Mom!\n" ]
+\end{code}
+\end{verbatim}
+there is no doubt about what should be considered the ``first
+column''. On the other hand, if you see a ``Bird track'' equivalent:
+\begin{verbatim}
+> main _ = [ AppendChan stdout "Hi, Mom!\n" ]
+\end{verbatim}
+obviously the initial \tr{>} should be stripped, but what about the
+space following? This matters if the code is to be put through, e.g.,
+a C pre-processor, which looks for \pl{#}'s in column~1.
+
+The solution I lean to is to have an option that says how much whitespace
+should be stripped off the front of Bird-track style code lines.
+
+%************************************************************************
+%* *
+\subsubsection[code-reading-and-printing]{Decouple code reading and printing styles}
+%* *
+%************************************************************************
+
+Code may come in either in code environments or in Bird-tracks. At
+present, it is printed in the same style as it came. This should
+remain the default.
+
+However, it would be nice to be able to say (with options), ``OK,
+print {\em all} the code as if it were in Bird-track form'' (or vice
+versa). This allows uniform presentation, while preserving
+programmers' preference for typing in one style rather than the other.
+
+%************************************************************************
+%* *
+\subsection[april91-old-ideas]{Old ideas that still haven't gone anywhere}
+%* *
+%************************************************************************
+
+These are ideas that have been around for a long time, HAVE NOT BEEN
+IMPLEMENTED, and no-one seems to have minded much.
+
+%************************************************************************
+%* *
+\subsubsection[recording-who-to-blame]{\pl{\owner{<name>}}}
+%* *
+%************************************************************************
+\index{owner@\owner}
+(Not \tr{lit2pgm}.) Give the ``name'' that should be listed as the
+``owner'' of a section. If no \tr{\owner} command has been seen, then
+the owner of the source file in which the first piece of text in the
+section was found is used.
+
+[I haven't really decided how this should work.]
+
+%************************************************************************
+%* *
+\subsubsection[test-burying]{Burying test cases in your document}
+%* *
+%************************************************************************
+
+The idea is that you can say:
+\begin{verbatim}
+\begin{test}{foo}
+<Weird stuff in here>
+\end{test}
+\end{verbatim}
+For this test \tr{foo}, the \tr{<weird stuff in here>} would somehow
+say how to run the test, what should be fed to standard input (etc.),
+and what results to expect on standard output, standard error, and
+perhaps certain output files.
+
+The idea is to put the (simple?) test cases right next to the code that
+will be exercised.
+
+The problem is: tests can do pretty arbitrary things, and I don't see
+any neat way to encode that fact. Simply bunging full-blown shell
+scripts into the middle of your literate program hardly seems the
+solution. Hmmm.....
+
+If we had them: test environments don't nest.
+
+See ????? (ToDo) for a note on using hidden comments to highlight test
+information.
+
+
+%************************************************************************
+%* *
+\subsubsection[recording-changes]{Recording changes to your documents}
+%* *
+%************************************************************************
+
+Vaguely like the test case stuff, you might say:
+\begin{verbatim}
+\begin{change}
+<who> & <when> & <tag> & <description of first change> \\
+<who> & <when> & <tag> & <description of second change> \\
+... and so on ...
+\end{change}
+\end{verbatim}
+This is intended to be like the ChangeLog stuff supported in Emacs
+(\tr{C-x 4 a}). It really only makes sense to use it after software
+is no longer undergoing cataclysmic change (after it is released
+perhaps?).
+
+Anyway, the idea is to record your change notes right next to where
+you make them. [The program(s) to extract these notes and to collate
+them in the manner of your choice are not written yet.]
+
+These change environments don't nest.
diff --git a/web/glasgow/lit2x-0.16/literate/doc/caveats.lit b/web/glasgow/lit2x-0.16/literate/doc/caveats.lit
new file mode 100644
index 0000000000..bb96edd629
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/caveats.lit
@@ -0,0 +1,45 @@
+\section[Caveats]{Caveats: bugs and foibles}
+
+As mentioned in \sectionref{clunky-implementation}, the initial
+implementation of this literate-programming system is delicate at
+best.
+
+\begin{enumerate}
+\item
+Environment-commands should be on lines of their own, and preferably
+start in column~1; the latter is especially important for verbatim
+environments.
+
+\item
+The line numbers reported with errors stand a fair chance of being
+wrong or even laughably irrelevant. \LaTeX{} doesn't report errors in
+terms of their original source anyway at all... (urgh)
+
+\item
+\tr{\Define}-itions (incl.~the built-in ones for \Haskell{},
+\LaTeX{}, etc.) are expanded inside \tr{\tr} and friends.
+
+\item
+You can get confused \tr{\items} (in enumerations, etc.) if you have:
+\begin{verbatim}
+\item[... stuff here... ] ...................... ]
+ right bracket on the same line -------------------^
+\end{verbatim}
+The solution (and it's better style anyway) is to put \tr{\items} on
+lines of their own. This is a vestige of the implementation...
+
+\item
+Don't put \tr{\index} commands inside footnotes. There are probably
+some other related restrictions... (ToDo)
+
+\item
+Tabs in code will be expanded to spaces. This matters only if you
+have tabs in string constants, or some such (which you shouldn't,
+because it's hard for the reader of your code to see what you've done;
+use \tr{\t} or the equivalent).
+
+\item
+If you use the cross-referencing (\tr{-D}, I think), you have the
+annoying feature of cross-referencing to things very near by, even on
+the same page. I don't know how to stop this.
+\end{enumerate}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/habits.lit b/web/glasgow/lit2x-0.16/literate/doc/habits.lit
new file mode 100644
index 0000000000..597708b8a0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/habits.lit
@@ -0,0 +1,34 @@
+\section[Habits]{A checklist of good literate habits}
+
+[Suggestions welcome. Haven't worked on this in a while.]
+
+\begin{itemize}
+\item
+Express your ideas in a way amenable to plain ASCII representation, as
+well as that of full-blown \TeX{} typesetting. For example, serious
+\TeX{} math-mode stuff is not really on (even if you can get it past
+\tr{lit2latex}). If you find this constraint a big problem, you may
+well be using the wrong tool for the job.
+
+\item
+If you test your document first as an Info file (i.e., use
+\tr{lit2texi} to process it), once that is right then it is very
+likely that the \LaTeX{} side of things (using \tr{lit2latex}) will
+come out right as well. The reverse is not true.
+
+\item
+Follow the convention that the sectioning in every file begins with a
+\tr{\section}. For details on how to do sectioning, please see
+\sectionref{How_to_section}.
+
+\item
+Arrange your document so that your Info nodes come out no more than
+two screenfuls' long. Very long nodes obviate the whole point of Info
+documents.
+
+\item
+It's hard to make up good sets of Info node names. First, they must
+be unique! Second, it's best if the uniqueness is in the first few
+characters, so that nodename completion may be used to most advantage.
+
+\end{itemize}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/highlights.lit b/web/glasgow/lit2x-0.16/literate/doc/highlights.lit
new file mode 100644
index 0000000000..5a7f9b3d5c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/highlights.lit
@@ -0,0 +1,354 @@
+\section[Highlights]{Literate programming, Glasgow style}
+
+Literate programming is a style that tries to maximise humans'
+understanding of programs by full-scale use the tools of the
+description trade (typesetting, indexing, etc.) to say what a program
+does and how it works. The power of literate programming is in the
+synergy between writing code and documentation in a unified
+framework.
+
+So, for example, in Knuth's original WEB
+system [ToDo: add reference(s)] ``code'' and ``text'' may be
+intermingled as much as you like, the pieces of ``code'' may appear in
+any order (even though it's only glorified Pascal), and quite
+substantial cross-referencing and indexing (not to mention
+\TeX{}-based typesetting) is built in. Programs are just documents
+for people to read and enjoy which happen to have
+machine-manipulable code ``buried'' in them.
+
+% An essential feature of a literate program is that the
+% compilable/executable program and the document describing that program
+% come from {\em the same source}. A most desirable feature of a
+% literate-programming system is that the painful-by-hand parts of
+% documents, such as indexing and cross-referencing, are provided
+% automatically.\footnote{This characterization of literate programming
+% follows Van Wyk's column in CACM, May 1990.}
+%
+% This system for literate programming meets the criteria above. The
+% first \sectiontype{Highlights} lists some of its features; the second
+% \sectiontype{notation-tut} describes the \LaTeX{}-looking markup
+% language and document structure; the third
+% \sectiontype{Programs} says how to run these programs for literate
+% programming.
+
+\subsection[Glasgow-objectives]{Objectives of our Glasgow system}
+
+With our Glasgow system, your ``program'' is a \LaTeX{}-like document, with
+the compilable/executable code marked off by a \tr{\begin{code}}
+... \tr{\end{code}} pair (or equivalent shortcut notation). From
+there, your ``program'' may be (a)~compiled/interpreted [by extracting
+the embedded code and feeding it to a ``normal'' compiler/interpreter];
+(b)~turned into a beautiful typeset document to be smeared onto dead
+trees, or (c)~turned into an on-line viewable/jump-aroundable
+document.
+
+Here are the specific (distinctive?) objectives of the Glasgow system.
+
+\subsubsection[on-line-form]{Programs/documents in an on-line form}
+
+The people-oriented documents produced by literate-programming systems
+are usually on paper (this system provides those, too). For working
+programmers, their good properties are largely overshadowed by one
+fact: paper documents go stale quickly. Also, large programs turn
+into not-so-navigable large piles of dead trees. Surely we can do
+better!
+
+Note our emphasis on presenting work-in-progress, as opposed to a
+system that emphasises the presentation of the final perfect
+programming gem.
+
+Our goal is that these on-line documents should be the medium of
+choice for programmers' daily reference. (APRIL91: See the note about
+``literate Para mode'' in \sectionref{literate-para-mode}.)
+
+Our choice for an on-line format is the GNU Info format, a primitive
+ASCII-only sort-of hypertext system. The main reason for this choice
+is to let the GNU people do as much of our programming for us as
+possible! The program \tr{info} can display Info files on just about
+any kind of terminal; \tr{xinfo} works with the X~Window System; the
+ubiquitous GNU~Emacs has an ever-improving Info mode.
+
+\subsubsection[medium-scale]{Programming on a medium scale}
+
+We aren't really interested in programming-in-the-small (one person, a
+few hundred lines of code), and we don't know about programming in the
+large (hundreds of programmers, millions of lines of code); our target
+audience is five-person projects working on programs the size of, say,
+a \Haskell{} compiler :-)
+
+\subsubsection[language-independence]{Programming language independence}
+
+The system may be used for literate programming with any programming
+language. However, the quality of the indexing, typesetting, etc.,
+support will vary, depending on whether that language is ``supported''
+or not. Fortunately, the current implementation, while clunky (see
+\sectionref{clunky-implementation}, makes it easy to add better
+support for a given programming language.
+
+See \sectionref{reordering-unemphasis} for a related comment about
+code re-ordering.
+
+\subsubsection[code-verissimilitude]{Program code written exactly as in illiterate programs}
+
+You put executable/compilable code into your literate programs by
+inserting it in a \tr{\begin{code}/\end{code}} environment (or the
+``Bird-track'' equivalent); for example:
+\begin{verbatim}
+\begin{code}
+main _ = [ AppendChan stdout "Hello, world!\n" ]
+\end{code}
+\end{verbatim}
+The principle is: you can write code inside a
+\tr{\begin{code}/\end{code}} environment {\em exactly} as you would in
+an illiterate program in the same language.
+
+This brings up a dichotomy that pervades literate programs: everything
+in the program is either {\em code}\index{code (vs text)} (stuff in a
+code environment, or equivalent) or {\em text}\index{text (vs code)}
+(everything else).
+
+\subsubsection[ASCII-declarative-markup]{Use of ASCII-based files, ``declarative'' markup}
+
+ASCII-based files (as opposed to some weird binary ``internal
+format''): so you can read the files directly and e-mail them to your
+friends.
+
+Insisting on ASCII files means some kind of markup commands buried
+in the text.
+
+We want the markup to be ``declarative,'' that is, to say ``what you
+want'' rather than ``how to produce what you want.'' Section
+numbering, generation of a table of contents, much indexing work,
+cross referencing, creating of the Info ``node'' structure, etc.,
+etc., is done automagically.
+
+Our starting-point choice for a ``declarative'' markup notation was
+\LaTeX{}, because that's what we know (and so do a lot of other
+people). You could make the case that GNU's Texinfo format would've
+been better, esp.~given some of our other objectives. Or: you could
+argue that we should've chosen a completely different notation,
+because some people look at our literate files and think they {\em
+are} \LaTeX{}, which they are not.
+
+The most important parts of our \LaTeX{}-like notation are introduced
+in \sectionref{notation-tut}, and the whole mess is exhaustively
+described in \sectionref{Command_reference}.
+
+\subsubsection[hierarchical-structure]{Use of hierarchical structure}
+
+That is: programs/documents divided into sections, subsections within
+sections, subsubsections...
+
+Hierarchy is a very powerful structuring tool, but its utility for
+wading around a large sea of code is not apparent. APRIL91: See the
+comments about a ``literate Para mode'' in
+\sectionref{literate-para-mode}.
+
+See also \sectionref{sectioning-large-documents}.
+
+\subsubsection[separate-compilation]{``Separate compilation'' for large programs/documents}
+
+This really follows from the size of project we're trying to support;
+it's just {\em too slow} to have to slurp in the {\em whole} program
+text and do anything... (It's pretty slow as it is :-)
+
+Separate compilation of the embedded code: Use the normal mechanisms
+of your programming language. For example, if you have a literate C
+file, \tr{foo.lc}, then you would extract the code into \tr{foo.c}
+(command: \tr{lit2pgm foo.lc}) and compile as normal (\tr{gcc -c foo.c}).
+
+``Separate compilation'' of the (\LaTeX{} and (Tex)info)
+document-generating tasks: this is harder and quite a lot of work {\em
+has} to be done at ``link time''. What happens: the initial
+``separate compilations'' of all the individual files in a
+program/document (e.g., \tr{lit2texi -c foo.lc} or
+\tr{lit2latex -c foo.lc}) produce intermediate files (\tr{*.itxi} and
+\tr{*.itex} files, respectively). These are then consulted when
+a ``link'' is done (e.g., \tr{lit2latex root.lit}, where \tr{root.lit}
+\tr{\inputs} the other files).
+
+(It's complicated: use Makefiles!)
+
+\subsubsection[one-file-many-purposes]{Using one file in several ways}
+
+Say you're writing a \Haskell{} compiler :-), which includes the
+source code for a typechecker. On the one hand, you want this to be
+included in ``the book'' (document) that is the whole compiler.
+However, you may also want to have a ``typechecker document'' that is
+itself self-contained (if only because the ``book'' is so big). Going
+further: perhaps one module of your typechecker is so amazing that you
+want to publish it as a paper.
+
+You could make copies of files, edit them, etc., but that's tacky, and
+against a most deeply-held principle of literate programming: that you are
+looking at {\em the} source code for the program being described.
+
+As it stands, this system lets you put \tr{\begin{onlystandalone}} and
+\tr{\end{onlystandalone}} around pieces of your files that only apply
+in the ``do this as a standalone document'' case; similarly,
+\tr{\begin{onlypartofdoc}} and \tr{\end{onlypartofdoc}} for stuff that
+only applies in the ``the glorious whole'' case.
+
+APRIL91: I am fairly convinced I got this {\em wrong} and believe that
+this stuff would be much better handled with a pseudo-``C
+pre-preprocessor'' (one that does not look inside code blocks [see
+deeply-held principle above; \sectionref{code-verissimilitude}]); see
+\sectionref{pseudo-C-preprocessor}.
+
+\subsection[Glasgow-NON-objectives]{NON-Objectives of our system}
+
+\subsubsection[not-reinvent-LaTeX]{Not to reinvent \LaTeX{} (or any other extensible notation)}
+
+Just as with Texinfo, our markup notation has a {\em fixed} set of
+commands. We don't have a \tr{\define} command that let's you define
+new macros in terms of old ones. This is for simplicity, I suppose.
+
+APRIL91: see the note about fake ``C pre-processing'' in
+\sectionref{pseudo-C-preprocessor}.
+
+\subsubsection[reordering-unemphasis]{An un-emphasis on code-reordering}
+
+Some programming languages have a narrow-minded idea about what order
+the pieces of a program must be presented (e.g., COBOL: identification
+division, then file division, then data division [how many of you knew
+this :-]), and some literate-programming systems provide lots of
+machinery to get around this orderly intransigence.
+
+We write in \Haskell{}, which is relatively open-minded about the
+order in which functions, etc., are presented. Re-splicing together
+code from dispersed program fragments doesn't buy you much---and we
+think the same is true for most modern or semi-modern programming
+languages. Therefore, this system has only primitive support for
+reordering code.
+
+\subsection[Other-Glasgow-features]{Other features of our Glasgow system}
+
+\subsubsection[sectioning-large-documents]{Sectioning support for large documents}
+
+The main thing we've done here is {\em change} the sectioning commands
+(vs \LaTeX{}) so it's easy to re-arrange chunks of the hierarchy.
+Also, a default Info ``node'' structure is worked out, based on the
+sectioning information. (Veteran Texinfo hackers will appreciate the
+joys of not typing error-prone \tr{@menu}s.)
+
+Sectioning in an individual file should {\em always} begins at
+\tr{\section}; such files should then glued together in a ``root
+file'' with \tr{\input} commands interspersed with \tr{\upsection} and
+\tr{\downsection} commands. \tr{lit2latex}/\tr{lit2texi} combine your
+files, putting appropriate real-\LaTeX{}/Texinfo sectioning commands
+(\tr{\part}, \tr{\chapter}, etc.) in the right places.
+
+A side-effect of diverging from \LaTeX{} sectioning is that we can
+support deeper nesting of sectioning commands.
+
+It's also neat to be able to change your mind about whether you want
+to start with (\LaTeX{}-speak...) parts, chapters, sections, or
+whatever...
+
+Please see \sectionref{Sectioning} for further details about this
+whole mess.
+
+\subsubsection[automatic-indexing]{Automatic indexing of your code}
+
+An attempt is made to index all the ``interesting things'' in the code
+parts of your program. The success of this enterprise depends on the
+degree to which the language you are using is supported.
+
+In a paper manifestation, you'll get nice neat indexes, like we're
+used to. In an on-line
+manifestation, you would like to use the information to ``point and
+jump'' (our Info-based implementation does this, perhaps clumsily).
+
+APRIL91: See \sectionref{multiple-indexes} for latest thoughts about
+indexing. Also, I've put some comment about free-text retrieval in
+\sectionref{free-text-index}.
+
+\subsubsection[manual-indexing]{Indexing by hand}
+
+Indexing your text (vs your code) is not automatic. You do it by hand
+with \tr{\index{<stuff>}} commands. The format of the \tr{\index}
+commands is a simplified (?) form of \tr{makeindex} commands.
+\Sectionref{Indexing} gives the details.
+
+\subsubsection[automatic-cross-referencing]{Automatic cross-referencing of your code}
+
+Your code may also be automatically cross-referenced; again, it's
+based on finding ``interesting things'' in your code; furthermore, it
+depends on distinguishing between ``definitions'' and ``uses'',
+because the main purpose of cross-referencing is to let you move quickly
+from a ``use'' (e.g., of a function) to its ``definition''.
+
+APRIL91: Sometimes you would really like to be able to go from a
+definition to all of its uses. Perhaps this should be an option.
+
+Cross-referencing is automatically OFF when producing \LaTeX{}
+documents (we found it mainly cluttered) and ON when producing Info
+files (which lets you jump to the definitions through a node's menu).
+
+\subsubsection[shortcut-notations]{Shortcut notations}
+
+Within non-code parts of documents, code snippets may be included
+between `at' signs; e.g., \tr{@f x y = y@}---appropriate formatting,
+indexing, etc., will be done.
+
+APRIL91 COMMENT: I need to clarify the proper use of these \tr{@}s. I
+also need to figure what to do when \tr{@}s are not the right thing!
+(I think Texinfo has an over-proliferation of commands for marking off
+this and that in the text.) See \sectionref{code-in-text-formatting}.
+
+For the ordinary text to be shown in a typewriter font (much used in
+user's guides, for example), you may use the \tr{\tr{<text>}} command;
+the only restriction on \tr{<text>} is that braces must be balanced.
+The same trick for ``plain'' (roman) font is \tr{\pl{<text>}}.
+[APRIL91: See \sectionref{diff-fonts-in-text} for further thoughts
+about fonts in your text.]
+
+APRIL91: See also: \sectionref{BNF-grammars}.
+
+\subsubsection[TeX-to-ASCII]{The great ``\LaTeX{} to ASCII'' problem solved!}
+
+(Well, not quite...) A literate program looks an awful lot like a
+\LaTeX{} document. If you convert the program to an Info file, then
+run the \tr{info2ascii} script [which I haven't written yet :-] over
+it, you'll have a quite-reasonable all-ASCII nicely-formatted version
+of your \LaTeX{}-ish input.
+
+\subsection[Glasgow-NON-features]{Shortcomings of our system}
+
+\subsubsection[texinfo-limits]{Limits because of the Texinfo intermediate representation}
+
+We produce our on-line viewable GNU Info files by going through their
+Texinfo format. If something cannot be represented easily in Texinfo
+(which doesn't do things not easily representable in character-only
+ASCII), it ain't in our system. This leads to the following {\em very
+notable} shortcomings:
+\begin{enumerate}
+\item
+No graphics, pictures, or sound.
+\item
+No fancy mathematical stuff of the sort \TeX{}/\LaTeX{} is so good at.
+Note: we would like to provide enough {\em basic} mathematical stuff
+so you aren't hamstrung by this restriction.
+\end{enumerate}
+
+\subsubsection[clumsy-node-namespace]{Node namespace is not ``neat''}
+
+For all practical purposes, it's {\em your problem} to make sure that
+you don't get nodename clashes. This is really uncool.
+
+APRIL91: Some ideas for partial alleviation of making-up-nodenames
+weariness, see \sectionref{revised-sectioning}.
+
+Barring that, a good discipline for making up unique nodenames would
+be helpful (I haven't found one yet).
+
+\subsubsection[clunky-implementation]{A clunky implementation}
+
+The principle has been: do as little work as possible. (What do you
+expect from the proponents of lazy functional programming?)
+
+The implementation is the Perl Script From Hell, with a supporting
+cast of the Flex Program From Hell, and a whole bunch of exceedingly
+useful programs written by other people, mainly the GNU
+Info/Texinfo-related programs and \tr{tgrind} (by Van Jacobsen). [We
+can pass along the source to all of these programs.]
diff --git a/web/glasgow/lit2x-0.16/literate/doc/install.lit b/web/glasgow/lit2x-0.16/literate/doc/install.lit
new file mode 100644
index 0000000000..8f4f9e1827
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/install.lit
@@ -0,0 +1,96 @@
+\section[lit-install]{Standalone installation of Glasgow literate programming}
+
+NOT DONE PROPERLY YET.
+
+Here are some short notes; they should work on a Sun4:
+\begin{enumerate}
+\item
+If you don't have \tr{perl}, go get it.
+
+\item
+If you don't have \tr{makeindex} (normally with the TeX distribution)
+and/or \tr{tgrind}, go get them, if you wish. You can easily get by
+without them, especially \tr{tgrind}.
+
+\item
+Customise for your local configuration, by creating a suitable
+\tr{mkworld/site.jm} file. We supply a \tr{site.dist} file that you
+can copy and work from.
+
+Setting \tr{PerlCmd} correctly is {\em vital}.
+
+All the Haskell-compiler stuff isn't important for the
+literate-programming system.
+
+Setting \tr{TgrindHelperCmd} is important if you're going to try the
+tgrind-ing stuff.
+
+Setting the things for installation (near the end) is {\em vital}.
+You will almost certainly need to set \tr{InstRootDir}, and perhaps
+some others. If you don't set anything, the literate-programming
+system will be installed (on a Sun4) in...
+
+\begin{tabular}{ll}
+/usr/local/bin/sun4 & things for the user to invoke (lit2mumble) \\
+/usr/local/lib/literate/sun4 & machine-specific support stuff \\
+/usr/local/lib/literate & machine-independent support stuff \\
+\end{tabular}
+
+\item
+OK, you should be ready to go! From the top of the distribution...
+\begin{verbatim}
+% cd lit2xxx-X.YY
+% ./STARTUP-literate >& startup.log
+\end{verbatim}
+Everything should proceed to an obviously-successful conclusion (check
+the log to see...).
+
+\item
+Test the system enough to see that it's not totally broken.
+Invoke \tr{lit2pgm}, \tr{lit2latex}, or \tr{lit2texi} directly from
+the \tr{literate/} directory, on some small test file of your choice,
+even something as simple as...:
+\begin{verbatim}
+\section[test]{Test section}
+This is a small test.
+\end{verbatim}
+Then try, perhaps:
+\begin{verbatim}
+% literate/lit2latex -v -c test.lit
+\end{verbatim}
+
+\item
+If things seem basically happy, you can safely install the system.
+\begin{verbatim}
+% cd literate
+% make -n install # trial run, just to see if it looks "right"
+% make install # for real!
+\end{verbatim}
+
+\item
+To make the documentation (some pre-built stuff is in the distrib):
+\begin{verbatim}
+% cd literate
+% make literate.dvi # or ...
+% make literate.info # or ...
+% make docs # to do both
+\end{verbatim}
+
+In the unlikely event you wanted to install it, continue with:
+\begin{verbatim}
+% make install-docs
+\end{verbatim}
+
+\item
+You can now either delete the source or just clean up:
+\begin{verbatim}
+% make clean
+\end{verbatim}
+
+\item
+Save a copy of your configuration file \tr{mkworld/site.jm} for next
+time.
+\end{enumerate}
+
+If you have problems, please report them to me,
+partain\@dcs.glasgow.ac.uk.
diff --git a/web/glasgow/lit2x-0.16/literate/doc/lang_ref.lit b/web/glasgow/lit2x-0.16/literate/doc/lang_ref.lit
new file mode 100644
index 0000000000..16652af006
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/lang_ref.lit
@@ -0,0 +1,472 @@
+\section[Command_reference]{\LaTeX{}-like markup commands: reference}
+
+This \sectiontype{Command_reference} assumes you are familiar with the
+tutorial-ish material in \sectionref{notation-tut}. It also assumes
+some familiarity with \LaTeX{}, in that I may say say, ``It works as
+in \LaTeX{}''.
+
+The lists below catalog the environments\index{environment}
+(\tr{\begin{...}/\end{...}} things) and commands\index{command}
+(backslashed \tr{\things}) of our Glasgow literate-programming notation.
+[For this clunky implementation, the \tr{\begin{...}} and \tr{\end{...}}
+delimiters should be on lines by themselves, beginning in the leftmost
+column.]
+
+Occasional mention is made of the main programs used to process
+literate files: \tr{lit2pgm}, which extracts the code from a file;
+\tr{lit2latex}, which creates real \LaTeX{} source from a file; and
+\tr{lit2texi}, which creates Texinfo source from a file (from which
+Info files can be made with \tr{makeinfo}).
+
+Little things first:
+\begin{itemize}
+\item
+In text, you should use the \TeX{} style of double quotes:
+\tr{``foo''}.
+\item
+In text, backslashed magic characters, e.g., \tr{\& \_ \# \$}, will
+produce the self-same de-backslashed magic characters in the output.
+\item
+Accents on characters (e.g., \tr{\'e}) are fine; they are tossed from
+Info files.
+\item
+You may safely use the italic correction \tr{\/}.
+\item
+At least the font-fiddling declarations \tr{\sc} and \tr{\tt} will
+work; they are heartily unrecommended.
+APRIL91: see the comments in \sectionref{diff-fonts-in-text}.
+Also, make them commands, not declarations?
+\end{itemize}
+
+Commands and environments (in alphabetical order):
+
+% I want to split these somehow so that info menus help one jump around
+
+\subsection*[\appendix]{\pl{\appendix}}
+\index{appendix@\appendix}
+Section numbering after this command is for appendices.
+(Has no effect on Info files. ToDo: it probably should.)
+
+\subsection*[\author]{\pl{\author{<text>}}}
+\index{author@\author}
+Please see under \tr{\maketitle}.
+
+\subsection*[center_environment]{\pl{center} environment}
+\index{center environment}
+As for \LaTeX{}. [APRIL91: Not implemented (and not sure how to do it
+easily on the Texinfo side), but I need to do something because Simon
+keeps using it.]
+
+\subsection*[\centerline]{\pl{\centerline{<text>}}}
+\index{centerline@\centerline}
+As for \LaTeX{}.
+
+\subsection*[\caption]{\pl{\caption{<text>}}}
+\index{caption@\caption}
+As for \LaTeX{}; likely to be unsatisfactory for Info files because the
+latter doesn't do figures.
+
+\subsection*[\clearpage-etc]{\pl{\clearpage} and \pl{\cleardoublepage}}
+\index{clearpage@\clearpage}
+\index{cleardoublepage@\cleardoublepage}
+As in \LaTeX{}; no effect on Info files.
+
+\subsection*[code_environment]{\pl{code} environment}
+\index{code environment}
+% could use some indexing here ???
+See \sectionref{code-in-doc}. Also, don't forget the \tr{pseudocode}
+environment.
+
+You cannot nest other environments inside code environments.
+
+\subsection*[comment_environment]{\pl{comment} environment}
+\index{comment environment}
+Text in a \tr{comment} environment will be output (perhaps with
+extra indentation, smaller font, etc.) if a \tr{\suppresscomments}
+command hasn't yet been encountered. [NB: \tr{\suppresscomments}
+doesn't work with \tr{lit2texi}.]
+
+A comment environment cannot include another comment environment.
+
+\subsection*[\date]{\pl{\date{<text>}}}
+\index{date@\date}
+As for \LaTeX{}; please see under \tr{\maketitle} for exact details.
+
+\subsection*[\define]{\pl{\define{<command>}{<replacement>}}}
+\index{define@\define}
+Ultra-simple macro substitution, NOT LIKE \LaTeX{}. The text for
+\tr{<command>} will be replaced with \tr{<replacement>}; no nesting,
+no funny characters, nothing fancy.
+Don't \tr{\define} the same \tr{<command>} twice, for
+example. Intended for customising documents; please see the note
+under \tr{\input}.
+
+Defaults are provided for \tr{\Haskell}, \tr{\LaTeX}, \tr{\TeX} and
+\tr{\ldots}. More defaults on request.
+
+APRIL91: see \sectionref{pseudo-C-preprocessor} for what I would
+REALLY like to do about ``defining''.
+
+\subsection*[description_environment]{\pl{description} environment}
+\index{description environment}
+As in \LaTeX{}.
+
+\subsection*[display_environment]{\pl{display} environment}
+\index{display environment}
+Similar to \tr{verbatim} (line-breaks are obeyed) but formatted in the
+prevailing font (not necessarily typewriter). There is a
+\tr{flushdisplay} environment as well.
+
+You can't nest one display environment inside another.
+
+\subsection*[\documentstyle]{\pl{\documentstyle[<style-options>]{<doc-type>}}}
+\index{documentstyle@\documentstyle}
+You do not have to the \tr{literate} \LaTeX{} style option; e.g.,
+\tr{\documentstyle[literate]{report}}, but it is probably a good idea
+so people don't think you're writing real \LaTeX{}.
+
+\tr{\documentstyle} has two magical actions: (1)~the type of
+document (report, article, etc.) determines the default value
+for \tr{\rootsectiontype}, and (2)~it indicates that a standalone
+document is being generated (not just a part of one). [APRIL91: bear
+in mind that this standalone business is in jeopardy.]
+
+\subsection*[\em]{\pl{{\em <text>}}}
+\index{em@\em}
+The \pl{\em} (emphasize) declaration works just as in \LaTeX{}.
+
+APRIL91: make it a command, not a declaration, i.e., \pl{\em{<text>}}?
+
+\subsection*[enumerate_environment]{\pl{enumerate} environment}
+\index{enumerate environment}
+As in \LaTeX{}.
+
+\subsection*[figure_environment]{\pl{figure} environment}
+\index{figure environment}
+Goes straight through for \LaTeX{}; ignored for Info files, meaning that
+whatever is inside won't ``float.'' (Remember: we don't really do
+figures; see \sectionref{texinfo-limits}.)
+
+\subsection*[flushdisplay_environment]{\pl{flushdisplay} environment}
+\index{flushdisplay environment}
+Same as the \tr{display} environment, except it is not indented
+relative to the left margin.
+
+You can't nest one flushdisplay environment inside another.
+
+\subsection*[flushverbatim_environment]{\pl{flushverbatim} environment}
+\index{flushverbatim environment}
+Same as the \tr{verbatim} environment except that text is not indented
+relative to the left margin.
+
+You can't nest other environments inside a flushverbatim environment;
+see the note in \sectionref{verbatim_environment}.
+
+\subsection*[\footnote]{\pl{\footnote{<text>}}}
+\index{footnote@\footnote}
+Footnotes work! NB: with \tr{makeinfo}, you may choose one of two
+ways of doing footnotes in an Info file. By default, they will be at
+the bottom of the node (style BN), as opposed to in a node of their
+own (style MN). [ToDo: update the makeinfo info]
+
+\subsection*[\heading]{\pl{\heading{<title>}}}
+\index{heading@\heading}
+A pseudo-sectioning command that formats \tr{title} as if it were a
+section heading (no numbering or any of that rot), but it doesn't put
+anything in the table of contents, no Info node, no anything weird.
+
+\subsection*[\index]{\pl{\index{<entry>}}}
+\index{index@\index}
+Roughly as for \LaTeX{} with \tr{makeindex}. Don't try anything too
+weird: for example, \tr{\index{<mumble>}} inside a footnote doesn't
+work. Warning: full-blown \tr{makeindex}-style indexing has been
+``simplified'': please see \sectionref{Indexing} for the full gory
+(but wonderful!) details.
+
+\subsection*[\input]{\pl{\input{<filename>}}}
+\index{input@\input}
+Be sure these are on lines by themselves and start in column 1. The
+argument should be the full filename---no implied suffix. Files will
+be searched for along the \tr{LITINPUTS} path, specified by an
+environment variable of the same name. The default path includes only
+your current working directory.
+
+\tr{\input}s are only followed at link time; if that's not what you
+want, either give the appropriate command-line flag (\tr{-n}) or use
+\tr{\inputnow}.
+
+APRIL91: see \sectionref{pseudo-C-preprocessor} for some thoughts
+about how inputting may be changed.
+
+\subsection*[\inputnow]{\pl{\inputnow{<filename>}}}
+\index{inputnow@\inputnow}
+These are \tr{\input}s that are followed always, no matter what.
+Otherwise, they are the same.
+
+APRIL91: \tr{\inputnow} may go away at any second.
+
+\subsection*[\insertribbon]{\pl{\insertribbon{<ribbon-name>}}}
+\index{insertribbon@\insertribbon}
+Used to insert the text of one code-ribbon into another; see
+\sectionref{code-in-doc}. Must share a line with nothing
+but whitespace. Not recommended.
+
+ToDo: needs to be made to work {\em outside} of code environments,
+rather than inside them.
+
+DOES NOT WORK WITH \tr{lit2pgm -q}! (which is what we often use.)
+
+\subsection*[itemize_environment]{\pl{itemize} environment}
+\index{itemize environment}
+As in \LaTeX{}. British spelling (``itemise'') also accepted.
+
+\subsection*[\label]{\pl{\label}}
+\index{label@\label}
+Free-standing \tr{\label}s [supposedly] work as expected in \LaTeX{};
+in Info files, a
+\tr{\label} is taken as just another name for the node the \tr{\label}
+is in. Determining which node it's in doesn't take account of
+\tr{\input}s---it's the one it ``appears'' to be in---which may not be
+what you want. You {\em really should} use node-names as labels
+(see \sectionref{Node_specifications})...
+
+Labels (and, therefore, nodenames) shouldn't have weird characters in
+them. Such labels (nodenames) will be studiously ignored.
+
+\subsection*[\listoffigures-etc]{\pl{\listoffigures} and \pl{\listoftables}}
+\index{listoffigures@\listoffigures}\index{listoftables@\listoftables}
+As for \LaTeX{}; has no effect on Info files, which don't do
+lists of figures or tables.
+
+\subsection*[\makeindex]{\pl{\makeindex}}
+\index{makeindex@\makeindex}
+Not necessary even for \LaTeX{}---one is inserted automagically just
+before \tr{\begin{document}}; has no effect on \tr{lit2texi}.
+
+\subsection*[\maketitle]{\pl{\maketitle}}
+\index{maketitle@\maketitle}
+Will work as in \LaTeX{} for simple cases, using values provided
+by \tr{\author{<author-stuff>}}, \tr{\title{<title-stuff>}}, and
+\tr{\date{<date-stuff>}}. The \tr{\\} line-breaker works. You
+die if you try anything weird.
+
+For better or worse, if you use the \tr{-g} option (to ``grab'' a
+subtree of text for printing), then it {\em does} matter if the
+\tr{\maketitle} is in the pre-amble (before
+\tr{\begin{document}}) or not. Please see \sectionref{Programs-and-options}
+for the sorry details.
+
+\subsection*[menu_environment]{\pl{menu} environment}
+\index{menu environment}
+In producing an Info file, text in a \tr{menu} environment is
+copied verbatim to create an Info menu. You must provide something
+that Texinfo can grok. This whole mess
+might be used in
+conjunction with \tr{\suppressmenu} [if \tr{\suppressmenu} were
+implemented yet].
+
+APRIL91: this should probably be nuked if the rawtexinfo environment
+comes online.
+
+\subsection*[\menuentry]{\pl{\menuentry{<tag>}{<description>}}}
+\index{menuentry@\menuentry}
+Requests that an extra menu entry be put at the {\em beginning} of
+this section's menu.
+
+\subsection*[\node]{\pl{\node{<node-spec>}}}
+\index{node@\node}
+(Ignored for \LaTeX{}.) Makes an extra node in the Texinfo file; the
+\tr{<node-spec>} is copied straight through to the output, so it's
+your problem to include something sensible.
+
+APRIL91: nuked if rawtexinfo environment comes in?
+
+\subsection*[\pounds]{\pl{\pounds<something-like-a-number>}}
+\index{pounds@\pounds}
+The \pl{\pounds} must be followed by: zero or more whitespace
+characters, a digit or a question mark, zero or more
+digits/question-marks/commas/full-stops/the-letters-K-or-M, and a
+digit/question-mark/the-letter-K-or-M. The Ks or Ms may be in
+lower-case. The mind boggles.
+
+\subsection*[onlyinfo_environment]{\pl{onlyinfo} environment}
+\index{onlyinfo environment}
+Only the Texinfo/Info extraction program(s) pay attention to stuff
+inside. Don't put code in here!
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+\subsection*[onlylatex_environment]{\pl{onlylatex} environment}
+\index{onlylatex environment}
+Only the \LaTeX{} extraction program(s) pay attention to stuff
+inside. Don't put code in here!
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+\subsection*[onlypartofdoc_environment]{\pl{onlypartofdoc} environment}
+\index{onlypartofdoc environment}
+The extraction programs pay attention to stuff inside only if they
+believe this is just a piece of a document (i.e., ``separate
+compilation'' is going on). As always, don't put code in here! See
+the \tr{\standaloneornot} command for a shortcut.
+
+% need an xref to how to separate-compile ...
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+\subsection*[onlystandalone_environment]{\pl{onlystandalone} environment}
+\index{onlystandalone environment}
+The extraction programs pay attention to stuff inside only if they
+believe that a standalone document is in the works (i.e., a
+\tr{\documentstyle} command has been seen or the \tr{-S} flag
+given). As always, don't put
+code in here! See the \tr{\standaloneornot} command for a shortcut.
+
+% need an xref to how to separate-compile ...
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+\subsection*[\pageref]{\pl{\pageref{<label-or-node-name>}}}
+\index{pageref@\pageref}
+In making \LaTeX{} documents, works as usual. In making Info
+files, treated as a \tr{\ref} (there is no concept of ``page'' in
+an Info document).
+
+\subsection*[\pl]{\pl{\pl}}
+\index{pl@\pl}
+Plain text, set in a roman font; equivalent to \tr{\mbox{\rm #1}}, except
+that the argument can include any old printable ASCII characters, including
+properly-nested braces (escaping them is irrelevant). If you want to
+do something weird, do it another way. Note that linebreaks within
+the \tr{\pl} are prevented.
+
+The equivalent typewriter thing is \tr{\tr}.
+
+APRIL91: see possible changes in \sectionref{diff-fonts-in-text}.
+
+\subsection*[\printindex]{\pl{\printindex}}
+\index{printindex@\printindex}
+Should be just before \tr{\end{document}}.
+In Info mode, generates a node `Index' at the same sectioning depth as
+your top-level sectioning commands.
+
+APRIL91: see possible changes in \sectionref{multiple-indexes}.
+
+\subsection*[pseudocode_environment]{\pl{pseudocode} environment}
+\index{pseudocode environment}
+Format the same way as in a \tr{code} environment, but the enclosed
+stuff is not subject to extraction by \tr{lit2pgm}.
+
+Other environments do not nest inside a pseudocode environment.
+
+\subsection*[quotation_environment]{\pl{quotation} environment}
+\index{quotation environment}
+As in \LaTeX{}.
+
+\subsection*[rawlatex_environment]{\pl{rawlatex} environment}
+\index{rawlatex environment}
+If lit2latexing, copies the body of the environment straight through.
+Otherwise, discard it.
+
+One trick you may need: because of the feeble implementation, the
+system may still try to ``follow'' an \tr{\input} inside a rawlatex
+environment (which it shouldn't). The solution is to ``hide'' the
+\tr{\input} so it isn't first on a line:
+\begin{verbatim}
+\begin{rawlatex}
+\begin{figure}
+{}\input{weird-fig.ps}
+\caption{Weird Figure}
+\end{figure}
+\end{rawlatex}
+\end{verbatim}
+
+\subsection*[\ref]{\pl{\ref{<label-or-node-name>}}}
+\index{ref@\ref}
+As for \LaTeX{}.
+
+\subsection*[\rootsectiontype]{\pl{\rootsectiontype{<real-sectioning-command>}}}
+\index{rootsectiontype@\rootsectiontype}
+Please see \sectionref{Sectioning}.
+
+\subsection*[\sectiontype]{\pl{\sectiontype{<nodename>}}}
+\index{sectiontype@\sectiontype}
+Please see \sectionref{sectiontype-and-ref}.
+
+\subsection*[\sectionref]{\pl{\sectionref{<nodename>}}}
+\index{sectionref@\sectionref}
+Please see \sectionref{sectiontype-and-ref}.
+
+\subsection*[\standaloneornot]{\pl{\standaloneornot{<ifso>}{<ifnot>}}}
+\index{standaloneornot@\standaloneornot}
+If doing standalone-document processing (i.e., a \tr{\documentstyle}
+seen or \tr{-S} flag given), use text \tr{<ifso>}; otherwise, use text
+\tr{<ifnot>}. Keep this on one line {\em by itself}, OK?; for longer
+things, use the \tr{onlystandalone} and \tr{onlypartofdoc} environments.
+
+APRIL91: this stuff is in SEVERE jeopardy of being nuked; see
+\sectionref{pseudo-C-preprocessor}.
+
+\subsection*[\suppresscomments]{\pl{\suppresscomments}}
+\index{suppresscomments@\suppresscomments}
+Best put in the preamble of your overall document (i.e., before
+\tr{\begin{document}}). Causes text in all subsequent \tr{comment}
+environments to be ignored. NB: only works in producing \LaTeX{}
+documents. (ToDo: fix this)
+
+%\item[\suppressmenu]
+%\index{\suppressmenu}
+%Put one in a section if you don't want a menu to be
+%automagically generated for that section. See about the
+%\tr{menu} environment above. [Not yet implemented.]
+
+\subsection*[table_environment]{\pl{table} environment}
+\index{table environment}
+Goes straight through for \LaTeX{}; ignored for Info files, meaning that
+whatever is inside won't ``float.''
+
+\subsection*[\tableofcontents]{\pl{\tableofcontents}}
+\index{tableofcontents@\tableofcontents}
+As for \LaTeX{}; adds extra stuff to the top-level menu in an Info file.
+
+\subsection*[tabular_environment]{\pl{tabular} environment}
+\index{tabular environment}
+Same format as \LaTeX{}, but anything magical beyond \tr{&},
+\tr{\\}, and \tr{\hline} will probably get you in trouble.
+
+Other environments don't nest inside a tabular environment.
+
+\subsection*[\title]{\pl{\title{<text>}}}
+\index{title@\title}
+Please see under \tr{\maketitle}.
+
+\subsection*[\tr]{\pl{\tr}}
+\index{tr@\tr}
+Set in typewriter font; equivalent to \tr{\mbox{\tt #1}}, except
+that the argument can include any old printable ASCII characters, including
+properly-nested braces (escaping them is irrelevant). If you want to
+do something weird, do it another way. Note that linebreaks within
+the \tr{\tr} are prevented.
+
+The equivalent non-typewriter thing is \tr{\pl}.
+
+APRIL91: see \sectionref{diff-fonts-in-text} for further comment on
+this stuff.
+
+\subsection*[verbatim_environment]{\pl{verbatim} environment}
+\index{verbatim environment}
+As in \LaTeX{}---line-breaks are obeyed and everything is in typewriter
+font. See also: the \tr{flushverbatim} and \tr{display} environments.
+
+You can't nest other environments inside verbatim environments. A
+trick (hack) you can use to put a verbatim environment inside another
+is to indent the inner one by one space, as in:
+\begin{verbatim}
+ \begin{verbatim}
+ ...
+ \begin{verbatim}
+ ...
+ \end{verbatim}
+ ...
+ \end{verbatim}
+\end{verbatim}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/lang_specific.lit b/web/glasgow/lit2x-0.16/literate/doc/lang_specific.lit
new file mode 100644
index 0000000000..2f0c7a625a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/lang_specific.lit
@@ -0,0 +1,50 @@
+\section[Language_specific]{Language-specific processing}
+
+This \sectiontype{Language_specific} describes the processing of code
+in documents that is done in a language-specific way. This is mainly
+to do with indexing, typesetting, and similar matters.
+
+First, however, we give the default rules used when the programming
+language used is unsupported or unknown.
+
+%-------------------------------------------------------------------
+\subsection[Default_rules]{Rules for unknown or unsupported languages}
+
+[Not finished yet.]
+
+No hidden comments or explicit index entries in code.
+
+%-------------------------------------------------------------------
+\subsection[Haskell_rules]{Language-specific rules for \Haskell{}}
+
+[This section is not finished yet.]
+
+An explicit code index entry comment is of the form:
+\tr{--idx::<whatever>}, on a line of its own.
+
+A hidden comment is of the form: \tr{--hide::<whatever>}, on a line
+of its own.
+
+%-------------------------------------------------------------------
+\subsection[Perl_rules]{Language-specific rules for \tr{perl}}
+
+[This section is not finished yet.]
+
+An explicit code index entry comment is of the form:
+\tr{#idx::<whatever>}, on a line of its own.
+
+A hidden comment is of the form: \tr{#hide::<whatever>}, on a line of
+its own.
+
+%-------------------------------------------------------------------
+\subsection[C_rules]{Language-specific rules for \tr{C}}
+
+[This section is not finished yet.]
+
+%-------------------------------------------------------------------
+\subsection[Fortran_rules]{Language-specific rules for \tr{FORTRAN}}
+
+[This section is not finished yet.]
+
+The FORTRAN-specific support was provided by Adriaan Joubert
+(adriaan\@dcs.qmw.ac.uk).
diff --git a/web/glasgow/lit2x-0.16/literate/doc/lang_tut.lit b/web/glasgow/lit2x-0.16/literate/doc/lang_tut.lit
new file mode 100644
index 0000000000..446a91c61d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/lang_tut.lit
@@ -0,0 +1,658 @@
+\section[notation-tut]{A \LaTeX{}-like document markup language (tutorial-ish)}
+\index{latex-like markup language@LaTeX-like markup language}
+
+Here is a simple silly literate \Haskell{} program:
+
+\begin{verbatim}
+\documentstyle[literate]{report}
+\rootsectiontype{\part}
+\begin{document}
+Here is my \Haskell{} program to send a message to my friends:
+\begin{code}
+main _ = [ AppendChan stdout (message ++ " to " ++ my_friends) ]
+\end{code}
+
+\section[message]{The Message}
+\begin{code}
+message = "Hello"
+\end{code}
+\subsection{Comments about the message and its implementation}
+\begin{enumerate}
+\item
+The message is given as a top-level pattern binding.
+\item
+The @message@ binding does not violate the monomorphic restriction;
+its type is \tr{[Char]}, which is not overloaded.
+\end{enumerate}
+
+\section[friends]{My friends}
+
+\begin{code}
+my_friends = ( \ y -> "Bob and Joe" ) 3
+\end{code}
+
+\printindex
+\end{document}
+\end{verbatim}
+
+Here are some things to see in this example (don't worry if it doesn't
+make sense first time):
+\begin{itemize}
+\item
+The compilable program (the parts between \tr{\begin{code}}s and
+\tr{\end{code}}s) is simply contained in marked-off parts of your
+document, and the code therein is completely ordinary (no special
+programming notation).
+
+Such {\em code}\index{code (vs text)} is one ``kind of stuff'' in your
+literate program; {\em text}\index{text (vs code)} is the other.
+\item
+The overall document is arranged hierarchically (\tr{\section},
+\tr{\subsection}, etc.) and looks an awful lot like a \LaTeX{}
+document.
+\item
+There is quite a bit about {\em what} makes up your document
+(sections, code, enumerated lists) and very little about {\em how}
+your document should be formatted (e.g., ``skip 2 lines''). This is
+``declarative'' markup.
+\item
+Your program code will be indexed automatically; the \tr{\printindex}
+command is how you say where you want the index included.
+\item
+You can refer to things-in-your-code in the text parts of your
+document, by enclosing the reference in \tr{@}'s, as in
+\tr{@message@}. The reference will be suitably indexed.
+\item
+The sectioning commands (e.g., \tr{\section}) are odd (if you are
+used to \LaTeX{}). Most important, a sectioning command gives a {\em
+relative} position in the hierarchy; this means that commands like
+\tr{\rootsectiontype} can be used to adjust the absolute sectioning in
+the final document. In this example, the topmost section would be a
+\LaTeX{} \tr{\chapter} by default, but it's been changed to be a \tr{\part}.
+\item
+More not-\LaTeX{} trivia: the optional argument to \tr{\section}
+serves both as a label name (for \tr{\ref}, etc.) and as a node name
+for GNU Info files.
+\end{itemize}
+
+The following sections describe the more interesting parts of our
+\LaTeX{}-like notation, illustrated in the example above. (Before
+that is a micro-tutorial on \LaTeX{} conventions, in
+\sectionref{micro-latex}.)
+\begin{itemize}
+\item
+As the example above showed, the sectioning commands diverge quite
+significantly from \LaTeX{}. \Sectionref{Sectioning} gives the full
+details about sectioning.
+\item
+The example shows how program code is included in a document in the
+simplest way: just begin \tr{\begin{code}} and \tr{\end{code}} around it.
+\Sectionref{code-in-doc} describes the more involved uses of this
+feature.
+\item
+\Sectionref{Cross_references} and \Sectionref{Indexing} describe how
+to take full advantage of the cross-referencing and indexing
+facilities in your literate programs.
+\item
+\Sectionref{Examples} is supposed to include several complete examples
+of literate programs but IT IS NOT FINISHED YET.
+\end{itemize}
+
+Remember: \Sectionref{Command_reference} is (supposed to be) a
+complete reference document about the \LaTeX{}-like commands you may
+safely use.
+
+\subsection[micro-latex]{A micro-tutorial on our \LaTeX{}-like conventions}
+
+\LaTeX{} is a document preparation system (described in a book of
+almost that name, by Leslie Lamport), and its notation is the basis of
+that used in this literate programming system.
+Unsurprisingly, one thing you can do with your literate programs is
+turn them into real \LaTeX{} documents (for typesetting), using the
+program \tr{lit2latex}.
+
+A few things to know about our literate-programming markup notation:
+\begin{itemize}
+\item
+Backslash (\tr{\}) is the starts-a-command character. Therefore,
+\tr{\item} and \tr{\/} are commands, but \tr{dog} and \tr{(+)} are
+just plain text.
+\item
+{\em Mandatory} arguments to a command are given inside curly braces. So,
+we would use \tr{\foo{bar}} to pass one argument to the command
+\tr{\foo}; we would use \tr{\bar{hey1}{hey2}} to pass two arguments to
+the command \tr{\bar}.
+\item
+{\em Optional} arguments to a command are given in square brackets and
+come before mandatory arguments. So, for example,
+\tr{\help[everyone]{lunch}} passes one optional and one mandatory
+argument to the command \tr{\help}.
+\item
+\tr{\foo} is a {\em command} called ``foo'', while \tr{\begin{foo}}
+\pl{<text in-between>} \tr{\end{foo}} is an {\em environment} called
+``foo'' with \pl{<text in-between>} being inside that environment.
+\item
+The above isn't everything you need to know.
+\end{itemize}
+
+\subsection[Sectioning]{Sectioning commands}
+\index{sectioning}
+
+[APRIL91: After you read this, you may want to see some proposed
+changes in \sectionref{revised-sectioning}.]
+
+\subsubsection[section<n>]{The \tr{\section<n>} command}
+
+There is really just one sectioning command:
+\begin{verbatim}
+\section<n>[Info-node-name]{Section heading}
+\end{verbatim}
+where \tr{<n>} is a positive integer, the sectioning depth. For example, you
+might have:
+\begin{verbatim}
+\documentstyle[literate]{book}
+\rootsectiontype{\chapter}
+\begin{document}
+\section1[Node-1]{The top}
+
+\section2[Node-2]{The next level}
+\section3[Node-3]{The bottom level}
+\section3[Node-4]{More on the bottom level}
+
+\section2[Node-5]{Second part of the middle level}
+\section3[Node-6]{Bottom level, next section}
+\section3[Node-7]{Last section on bottom level}
+\end{document}
+\end{verbatim}
+As a convenience, the following synonyms are supported:
+\begin{verbatim}
+\section \section1
+\subsection \section2
+\subsubsection \section3
+\subsubsubsection \section4
+\end{verbatim}
+
+Saying \tr{\rootsectiontype{\chapter}} causes \tr{\section1},
+\tr{\section2}, and \tr{\section3} to be translated into the \LaTeX{}/Texinfo
+commands \tr{\chapter}, \tr{\section}, and \tr{\subsection},
+respectively. This system supports deeper section nesting than
+\LaTeX{} (12 levels vs.~7).
+
+If you want a section heading but don't want anything to appear in the
+table of contents, put a \tr{*} after the command name (just like
+\LaTeX{}); for example:
+\begin{verbatim}
+\subsection*[\pageref]{\pl{\pageref{<label-or-node-name>}}}
+\end{verbatim}
+
+If you want something that looks like a section heading but really
+isn't (no table-of-contents entry, no Info node), you probably want
+the \tr{\heading{<title>}} command.
+
+[Support your local creaky implementation:
+you must put sectioning commands on lines of their own.]
+
+In making an Info file, the hierarchy of \tr{\section<n>}
+commands will be turned into a corresponding hierarchy of Info nodes.
+With \tr{info},
+you navigate along one level of the hierarchy with \tr{Next}- and
+\tr{Prev}-node links; you move up the hierarchy with \tr{Up}-node
+links; and you move down the hierarchy (e.g., from a \tr{\section<n>}
+to its \tr{\section<n+1>}s) by choosing from an
+(automatically-generated) Info menu.
+
+\subsubsection[How_to_section]{How to use \tr{\section<n>}}
+
+The presumption is that {\em every file in a literate document will begin its
+sectioning with a \tr{\section}} (equivalently, \tr{\section1}) and
+further sectioning will reflect a reasonable hierarchical structure
+{\em within} the file. You usually know this when you are typing in a
+particular file.
+
+What you often do {\em not} know is how the file fits into the larger
+document, and it is most annoying (as happens sometimes with \LaTeX{})
+to have to rename all \tr{\chapter}s to \tr{\section}s, or some such.
+The information on how things go together is usually in a ``root
+file,'' which sticks things together with \tr{\input},
+\tr{\downsection} and \tr{\upsection}; this example is typical:
+\begin{verbatim}
+ \section[Desugar_match]{@match@: compiling out pattern-matching}
+ \downsection
+ % each of the following files would start with a \section
+ \input{Match.lhs}
+ \input{DeTwiddle.lhs}
+ \input{MatchCon.lhs}
+ \input{MatchLit.lhs}
+ \upsection
+\end{verbatim}
+
+The \tr{\upsection}s and \tr{\downsection}s determine what actual
+\LaTeX{}/Texinfo sectioning command is generated for a particular
+\tr{\section<n>} command. Unfortunately, the desired \LaTeX{}/Texinfo
+sectioning command for the {\em top} section in your hierarchy depends
+on the kind of document you are producing. For example, should it be
+a \tr{\part} or a \tr{\chapter}? The solution here is to let you
+choose, with the
+\tr{\rootsectiontype{\foo}}\index{rootsectiontype@\rootsectiontype}
+command. It says that \tr{\section1}s at the ``top level'' should be
+typeset as \LaTeX{}/Texinfo \tr{\foo}'s. The defaults based on the
+\tr{\documentstyle} should usually be adequate:
+\begin{verbatim}
+\documentstyle \rootsectiontype
+
+article \section
+report \chapter
+book \chapter
+\end{verbatim}
+For a report, a useful variant might be \tr{\rootsectiontype{\part}}.
+
+\subsubsection[sectiontype-and-ref]{The \tr{\sectiontype} and \tr{\sectionref} commands}
+
+Another annoying thing with \LaTeX{} sectioning is to type
+\tr{Section~\ref{foo}} only to have \tr{foo} turn out to be a ``chapter''
+(not a ``section''). In this system, you can type
+\tr{\sectiontype{Node-name}}\index{sectiontype@\sectiontype} and the type of the
+sectioning command at node \tr{Node-name} (e.g., ``chapter,''
+``section'') will be inserted [any unit below sections will be called
+``section'']. To have the inserted text be
+capitalised, use \tr{\Sectiontype{Node-name}}.
+
+For the common idiom,
+\tr{\sectiontype{Node-name}~\ref{Node-name}}, you may use
+\tr{\sectionref{Node-name}}\index{sectionref@\sectionref}
+(similarly for \tr{\Sectionref}).\index{sectionref@\Sectionref}
+[I use this all the time. --WDP]
+
+\subsubsection[Node_specifications]{GNU Info node specifications with \tr{\section<n>}}
+\index{node specification}
+
+[APRIL91: Don't overlook the new ideas in
+\sectionref{revised-sectioning}.]
+
+When making an on-line Info document from a literate program, the text
+between two sectioning commands is turned into an Info node.
+Moreover, the sectioning commands are used to determine how the nodes
+should be linked together---almost always in the hierarchical structure
+implied by the sectioning. However, you can tweak the process as much
+as you wish (almost no-one ever wishes...).
+
+Each \tr{\section<n>} command may have an optional ``node specification'',
+with which you may specify the name of the Info node and how it should
+be linked to other nodes. For common practice, I
+recommend giving a (unique) node name and enjoying the default links;
+for example:
+\begin{verbatim}
+\section[Foo-Sem]{Foo Semantics}
+\end{verbatim}
+Besides serving as the node name, \tr{Foo-Sem} will also be a \LaTeX{}
+\tr{\label} and may be \tr{\ref}'d or \tr{\pageref}'d: for example,
+you could say, ``The semantics are given in
+section\pl{~\ref{Foo_Sem}}''. (This is more likely to work than
+introducing a \tr{\label} of your own and \tr{\ref}'ing that.)
+
+%\begin{comment}
+%I've considered making an unadorned \tr{\section{Foo Semantics}} mean the
+%same thing as \tr{\section[Foo Semantics]{Foo Semantics}}, but I suspect
+%something bad would eventually happen.
+%\end{comment}
+
+Node names must not contain commas (and other unpleasant characters I
+don't want to think about) and spaces are probably asking for trouble.
+
+The next example shows the {\em general} form for a node
+specification, in which you want to specify all of a node's
+links by hand:\footnote{Ignore the rest of this
+\sectiontype{Node_specifications} unless you enjoy pain---it presumes
+some familiarity with Texinfo/Info
+specifics; see \tr{info info} and/or \tr{info texinfo}.}
+\begin{verbatim}
+\section1[This-Node,Next-Node,Prev-Node,Up-Node]{Bar Semantics}
+\end{verbatim}
+
+A \tr{?} may be given for any of the four node-names; then the default is
+used:
+\begin{enumerate}
+\item
+The default node-name is the section number.
+\item
+The default
+next-node is the one associated with the next same-level sectioning
+command (i.e., the next \tr{\section<n>} command if this is a
+\tr{\section<n>} command.
+\item
+Analogously for the default
+previous-node\ldots{}
+\item
+The default up-node is the last-seen
+next-level-up sectioning command, e.g., if at a \tr{\section<n>}, then the
+last \tr{\section<n-1>} command seen.
+\end{enumerate}
+Any text before the first
+\tr{\section} command goes in node \tr{Top}, which has node
+specification ``\tr{Top,,,(dir)}''.
+
+The recommended form \tr{\section[Foo-Sem]{Foo Semantics}} is
+just short for \tr{\section1[Foo-Sem,?,?,?]{Foo Semantics}}.
+
+Additional Info nodes that are unrelated to sectioning commands may be
+added with the \tr{\node} command. [Note: not well tested.]
+
+% To prevent a node being generated for a sectioning command, give the
+% node specification \tr{NO-NODE}, as in \tr{\section[NO-NODE]{Foo}}.
+
+If you want a \LaTeX{}-style sectioning command (e.g., to
+specify a table-of-contents entry), use \tr{onlyinfo} and \tr{onlylatex}
+environments.
+
+\subsection[code-in-doc]{Including program code in your document}
+
+Central to literate programming is having program code in your
+document that can be directly extracted and compiled/executed.
+
+\subsubsection[usual-code-in-doc]{The usual ways to put code in a documents}
+
+The most straightforward way to do this is to put all the code in a
+file in one or more \tr{\begin{code}} ... \tr{\end{code}}
+environments---the code can then be extracted (in the order it appears
+in the text) and fed to your favourite compiler/interpreter/whatever.
+
+An equivalent notation preferred by some is ``Bird tracks'', so-called
+because it started with Richard Bird (and because Cordy calls them
+that); lines starting with a \tr{>} are extracted; for example:
+\begin{verbatim}
+>main _ = [AppendChan stdout "hello, world\n"]
+\end{verbatim}
+is equivalent to:
+\begin{verbatim}
+\begin{code}
+main _ = [AppendChan stdout "hello, world\n"]
+\end{code}
+\end{verbatim}
+A block of Bird-tracked code lines must have a blank line before and
+after (not having one usually indicates a typo).
+
+\begin{comment}
+ToDo: Simon wants to know how code looks in (a)~a \LaTeX{}'d document and
+(b)~an Info'd document.
+\end{comment}
+
+\subsubsection[ribbons-details]{Code ribbons: the fancy stuff}
+
+Both of the above are shorthand notation for messier stuff going on
+underneath... Strictly speaking, the code in a particular document is
+made up of one or more
+{\em ribbons}\index{ribbons, code}\index{code ribbons} of code. For
+example,
+\begin{verbatim}
+A common thing to say to the world is ``Hello, world!''
+\begin{code}[hello-goodbye]
+void HELLO() { printf("HELLO, WORLD!\n"); }
+\end{code}
+
+However, you might want to be less exuberant:
+\begin{code}[wimp]
+void hello() { printf("hello, world!\n"); }
+\end{code}
+
+And perhaps you are trying to tune out, not tune in.
+\begin{code}[hello-goodbye]
+void goodbye() { printf("Good-bye, cruel world...\n"); }
+\end{code}
+\end{verbatim}
+
+As always, code to be extracted goes inside a
+\tr{\begin{code}}...\tr{\end{code}}; the {\em optional} argument after
+\tr{\begin{code}} is the name of the code-ribbon to which the
+program-text belongs. The example above has two ribbons,
+\tr{hello-goodbye} and
+\tr{wimp}. You can extract any code-ribbon(s) you wish [see
+\tr{lit2pgm}'s -r option]; the disjoint
+pieces of a particular ribbon (e.g., \tr{hello-goodbye} above) are
+catenated together in the order seen.
+
+Usually, this ribbon-business is just a bother, so there is the good
+ol' default ribbon, \tr{main}. For example, the
+way-you-normally-write-things:
+\begin{verbatim}
+\begin{code}
+void adieu() { printf("Adieu, cruel world...\n"); }
+\end{code}
+\end{verbatim}
+is actually short for:
+\begin{verbatim}
+\begin{code}[main]
+void adieu() { printf("Adieu, cruel world...\n"); }
+\end{code}
+\end{verbatim}
+
+Unsurprisingly, \tr{main} is the default code-ribbon when one is in
+the ribbon-extraction business. Similarly, code included
+with \tr{>} signs in the leftmost column (``Bird tracks'') is just
+tacked onto the \tr{main} ribbon, too:
+\begin{verbatim}
+>void
+>adieu()
+>{ printf("Adieu, cruel world...\n"); }
+\end{verbatim}
+
+\subsubsection[reordering-with-insertribbon]{Code reordering with \tr{\insertribbon}}
+
+If you are feeling particularly notorious, one piece of code may be
+appended to several ribbons (a comma-separated list of ribbon names,
+please---spaces are significant except for beside the commas):
+\begin{verbatim}
+\begin{code}[ribbon1, ribbon2, ribbon3]
+void adieu() { printf("Bon soir, cru\\'el world...\n"); }
+\end{code}
+\end{verbatim}
+
+To get the effect of WEB-like parameterless macros, one ribbon
+may use \tr{\insertribbon} to include a copy of another one, as in:
+\begin{verbatim}
+\begin{code}
+void adieu()
+ \insertribbon{message}
+\end{code}
+
+\begin{code}[message]
+{ printf("Adieu, cruel world...\n"); }
+\end{code}
+\end{verbatim}
+
+ToDo: CHANGE \tr{\insertribbon} SO IT'S OUTSIDE OF code ENVIRONMENT.
+
+I don't recommend \tr{\insertribbon}. You can make a terrible mess
+with it. I haven't tested it for months.
+
+\subsubsection[pseudocode]{Stuff that looks like code but isn't}
+
+If you want to include alternate versions of code (for illustrative
+purposes, presumably), to be typeset as code but {\em not} subject to
+extraction by \tr{lit2pgm}, put the extra versions in \tr{pseudocode}
+environments.
+
+\subsubsection[magic-things-in-code]{Magic things you can put in your code}
+
+Generally speaking, you enter your program code inside a
+\tr{code} environment {\em exactly} as you would
+otherwise (the principle discussed in
+\sectionref{code-verissimilitude}), and it will appear in your
+documents as shown (nicely typeset, we hope). There are two magic
+things that you can put in your code that do not appear in your
+document (directly):
+\begin{description}
+\item[Index entries:]
+\index{code index entries, extra}\index{index entries, extra ones in code}
+Code is automagically indexed, but you may wish additional index
+entries of your own choosing.
+
+\item[Hidden comments:]
+\index{hidden comments}\index{comments, hidden}
+You will sometimes want comments in your actual code that you do not
+want printed. An example: you might want to record next to each code
+block the names of the the test files used to exercise it. This is
+{\em really boring} information to all but the most dedicated reader.
+\end{description}
+
+In both cases, the information {\em could} be provided outside the
+code environment (i.e., without any special construct), but it could
+quite easily get lost (code blocks can be big, even if they shouldn't
+be :-).
+
+In all cases, these annotations are in a form recognised as a comment
+by the compiler/whatever for that language. Please see
+\sectionref{Language_specific} for the exact form used for the
+language you are interested in. A \Haskell{} example of both magic
+bits might be:
+\begin{verbatim}
+\begin{code}
+main _ = [AppendChan stdout "Hello, world...?\n"]
+--idx:: world, state of
+--hide:: use testfile093.hs
+\end{code}
+\end{verbatim}
+
+[APRIL91: Yell if you really dislike (or like) these two forms of
+``magic things in code''.]
+
+\subsection[Cross_references]{Cross-referencing}
+
+For cross-referencing, the normal thing is to use node-names on
+sectioning commands as labels, and to \tr{\ref{<label>}} and
+\tr{\pageref{<label>}} them, as is the \LaTeX{} custom.
+\tr{\pageref}s are discouraged, as there is no concept of page numbers
+in Info files.
+
+Similarly, if you heave in a \tr{\label{<some text>}}, the Info side
+of things will assume that \tr{<some text>} is just another label for
+the current node [NOT IMPLEMENTED (ToDo)].
+
+APRIL91: Cross-referencing is normally used to help you move from a
+{\em use} of a code-thing to its {\em definition}. There should
+probably be an option to let you get cross-referencing that will also
+let you move from a definition to all of its uses.
+
+\subsection[Indexing]{Indexing}
+
+[APRIL91: changes are envisaged; see \sectionref{multiple-indexes}.]
+
+Indexing is assumed to work with the program
+\tr{makeindex}\index{makeindex}, so you should put a
+a \tr{\printindex}\index{printindex@\printindex} command where you want the
+index to appear (almost always just before \tr{\end{document}}).
+(A \LaTeX{} \tr{\makeindex}\index{makeindex@\makeindex} command is supplied
+automagically before \tr{\begin{document}}.)
+
+Roughly speaking, code portions of your document are {\em automatically}
+indexed, and then you index the text portion {\em manually}, with
+\tr{\index} commands.
+
+\tr{\index{<entry text>}} is the basic indexing command and offers a
+simplified \tr{makeindex} interface.
+\begin{itemize}
+\item
+If you want just plain simple ``foo'' to appear in the index, use
+\tr{\index{foo}}.
+\item
+If you want subitems in an index entry, separate them with \tr{!}s
+[useful].
+\item
+If you want separate text for sorting and printing an index entry, put
+the two texts in that order, separated by an unescaped \tr{@}.
+\item
+To put a \tr{!} or \tr{@} in your index entry, escape it with a
+backslash \tr{\}.
+\item
+All other (semi-normal) characters work as is.
+\end{itemize}
+
+I don't encourage trying to have index entries pop out in different
+fonts---it doesn't work in plain Info files. You can write devious
+\LaTeX{}/\tr{makeindex} code on your own...
+
+Code-stuff in text (stuff inside \tr{@...@}) is indexed automatically,
+just like ``real code''. What actually happens depends on the support
+for your programming language---\sectionref{Language_specific} gives
+all the language-specific indexing idiosyncracies. The {\em default}
+bare-bones mechanism is that whitespace-free code-in-text over three
+characters long (e.g., \tr{@typecheck@}) will generate an index entry.
+To suppress automatic indexing of a piece of code-in-text, put a
+\tr{\noindex}\index{noindex@\noindex} immediately following, as in
+\tr{@typecheck@\noindex}.
+
+As mentioned in \sectionref{magic-things-in-code}, you can add
+index entries for your code by inserting specially-formatted comments
+(this depends on how well your programming language is supported).
+For example, for \Haskell{}, you might use [NB: NOT IMPLEMENTED YET (ToDo?)]:
+\begin{verbatim}
+f x y z = (y z) x
+-- the next line is a comment that will cause an index entry
+-- equivalent to: \index{foo-bar-baz}
+--#idx::foo-bar-baz
+\end{verbatim}
+
+For a chunk of code, a mini-index pointing to the definitions of the
+things it refers to (one possible definition of ``things:'' top-level
+functions) will be produced right after the code. (For the Info file,
+as part of the menu for that node.)
+\begin{comment}
+The Info part is done; I'm still thinking about what should be done
+for \LaTeX{}.
+\end{comment}
+[APRIL91: this is one of the things contemplated in
+\sectionref{multiple-indexes}.]
+
+At least some provision has been made for ``stop lists'' for the
+automagical indexing (I'm not sure how well it works...). You put
+words/strings that are normally picked up by the indexing into a file,
+then tell the system this is your ``stop list file'' (\tr{-s} option,
+I think), meaning ``Don't index these things---I'm not interested.''
+
+\subsection[Examples]{Some complete examples [NOT FINISHED]}
+
+NOT FINISHED YET. Some day...
+
+Meanwhile, you will find some reasonable not-over-huge examples in the
+\tr{literate/tests} directory in the source.
+
+\subsubsection[Simple_example]{A simple example}
+
+\subsubsection[Typical_example]{A typical example}
+
+\subsubsection[Hairy_example]{A hairy example}
+
+\subsection[Shortcuts]{Helpful short-cut notations}
+
+APRIL91: There is discussion about these sorts of things scattered
+through the ``new ideas'' in \sectionref{april91-new-ideas}.
+
+\subsubsection[code-in-text]{Referring to code things in your text}
+
+In the text part of a literate program, one often wishes to refer to
+things in the code (e.g., function names) or have code expressions in
+the running text, and so forth. One would like this code-in-text to
+be typeset just like the real-code-parts (currently verbatim, but that
+could change). To mark off code-in-text, surround it with `at' signs:
+as in \tr{@code in text@}; to put an `at' sign in in-line code, you've
+got to put in two `ats': \tr{@x @@ (y, z)@}. Line-breaks are prevented
+inside ``attified'' code-text.
+
+Because things inside `at' signs are so often just what you want to be
+indexed, the rule is: if the at-signed thing contains no whitespace,
+an index entry is generated. (How to prevent indexing and how to do
+fancier things about indexing and cross-referencing are given
+\sectionref{Indexing}.)
+
+APRIL91: see comments in \sectionref{text-in-code}.
+
+\subsubsection[fonts-in-text]{Using different ``fonts'' in your text}
+
+[APRIL91: Be sure to see \sectionref{diff-fonts-in-text}.]
+
+The \tr{\tr{<text>}} command sets \tr{<text>} in typewriter font, with
+no need for escape characters or anything---provided the braces nest
+properly.
+
+The same trick using a ``plain'' (roman) font is
+\tr{\pl{<text>}}, to produce \pl{<text>}.
+
diff --git a/web/glasgow/lit2x-0.16/literate/doc/lit_mode.lit b/web/glasgow/lit2x-0.16/literate/doc/lit_mode.lit
new file mode 100644
index 0000000000..8428bdb20b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/lit_mode.lit
@@ -0,0 +1,3 @@
+\section[Lit-mode]{`lit-mode' for Emacs}
+
+There will be one sometime. I even know what I want to do\ldots{}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/literate.dvi b/web/glasgow/lit2x-0.16/literate/doc/literate.dvi
new file mode 100644
index 0000000000..167e3a2553
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/literate.dvi
Binary files differ
diff --git a/web/glasgow/lit2x-0.16/literate/doc/literate.info b/web/glasgow/lit2x-0.16/literate/doc/literate.info
new file mode 100644
index 0000000000..bf24b42031
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/literate.info
@@ -0,0 +1,3390 @@
+This is Info file literate.info, produced by Makeinfo-1.47 from the
+input file literate.texi.
+
+
+File: literate.info, Node: Top, Up: (dir)
+
+This guide introduces a suite of programs for literate programming.
+They support documentation as a natural part of programming; a
+program's organization focusses on understanding by humans.
+
+If you installing this system as a standalone entity, please see
+section *Note lit-install::, near the end.
+
+This document begins with a few words about literate programming, the
+objectives of this system, and the Neat Stuff that this system is
+supposed to do for you (i.e., cheap, tasteless self-promotion). See
+section *Note Highlights::.
+
+The real goods come next, most notably:
+ * an alleged "tutorial" on the LaTeX-like markup language in which
+ documents/programs are written (section *Note notation-tut::);
+
+ * a "reference manual" about the same markup language; this tends to
+ be what you consult once you are using the system (section *Note
+ Command_reference::);
+
+ * the programs/tools to mangle your documents/programs into useful
+ forms (section *Note Programs-and-options::). There are other
+sections, too, in greater-or-less states of usefulness.
+
+It would be a good idea to understand the rudiments of GNU Info files
+before reading much further -- type `info info' at your favourite Unix
+prompt. Or you could just ignore all mention of Info files...
+
+YOUR SUGGESTIONS FOR IMPROVING THIS SYSTEM ARE MOST WELCOME.
+
+DISCLAIMER: "Literate programming" is not my(WDP)/our area of
+expertise. This system has been developed mainly to suit our needs and
+has evolved on a grease-the-squeaky-wheel principle. However, we
+wouldn't bother to document it if we didn't think there was something
+to it!
+
+APRIL91 PROPOSALS: I am thinking about some changes to the system, NOT
+YET IMPLEMENTED. Discussion about most (all?) of them is gathered
+together in section *Note april91-proposals::. (You can find all
+discussion of proposed changes by grepping for "APRIL91".)
+
+SEPT92 THOUGHTS: Still haven't really worked on this system. I have
+typed a few further thoughts at the obvious place. I have fixed one or
+two bugs, and I have incorporated Adriaan Joubert's
+(adriaan@dcs.qmw.ac.uk) stuff for "literate Fortran," for which I am
+most grateful. (See, it really is easy to extend :-)
+
+For more information about "real" literate programming, the
+bibliography of literate programming in the (approx: ToDo) March 1991
+SIGPLAN Notices may be of use.
+
+* Menu:
+
+* Highlights:: Literate programming, Glasgow style.
+* notation-tut:: A LaTeX-like document markup language (tutorial-ish).
+* Command_reference:: LaTeX-like markup commands: reference.
+* Language_specific:: Language-specific processing.
+* Habits:: A checklist of good literate habits.
+* Caveats:: Caveats: bugs and foibles.
+* Programs-and-options:: Programs to process literate documents.
+* Info_etc:: Using your processed literate documents.
+* april91-proposals:: APRIL91 PROPOSALS.
+* sept92-thoughts:: SEPT92 THOUGHTS.
+* lit-install:: Standalone installation of Glasgow literate programming.
+* Index:: Index.
+
+
+File: literate.info, Node: Highlights, Next: notation-tut, Prev: Top, Up: Top
+
+Literate programming, Glasgow style
+===================================
+
+Literate programming is a style that tries to maximise humans'
+understanding of programs by full-scale use the tools of the
+description trade (typesetting, indexing, etc.) to say what a program
+does and how it works. The power of literate programming is in the
+synergy between writing code and documentation in a unified framework.
+
+So, for example, in Knuth's original WEB system [ToDo: add
+reference(s)] "code" and "text" may be intermingled as much as you
+like, the pieces of "code" may appear in any order (even though it's
+only glorified Pascal), and quite substantial cross-referencing and
+indexing (not to mention TeX-based typesetting) is built in. Programs
+are just documents for people to read and enjoy which happen to have
+machine-manipulable code "buried" in them.
+
+* Menu:
+
+* Glasgow-objectives:: Objectives of our Glasgow system.
+* Glasgow-NON-objectives:: NON-Objectives of our system.
+* Other-Glasgow-features:: Other features of our Glasgow system.
+* Glasgow-NON-features:: Shortcomings of our system.
+
+
+File: literate.info, Node: Glasgow-objectives, Next: Glasgow-NON-objectives, Prev: Highlights, Up: Highlights
+
+Objectives of our Glasgow system
+--------------------------------
+
+With our Glasgow system, your "program" is a LaTeX-like document, with
+the compilable/executable code marked off by a `\begin{code}' ...
+`\end{code}' pair (or equivalent shortcut notation). From there, your
+"program" may be (a) compiled/interpreted [by extracting the embedded
+code and feeding it to a "normal" compiler/interpreter]; (b) turned
+into a beautiful typeset document to be smeared onto dead trees, or (c)
+turned into an on-line viewable/jump-aroundable document.
+
+Here are the specific (distinctive?) objectives of the Glasgow system.
+
+* Menu:
+
+* on-line-form:: Programs/documents in an on-line form.
+* medium-scale:: Programming on a medium scale.
+* language-independence:: Programming language independence.
+* code-verissimilitude:: Program code written exactly as in illiterate programs.
+* ASCII-declarative-markup:: Use of ASCII-based files, "declarative" markup.
+* hierarchical-structure:: Use of hierarchical structure.
+* separate-compilation:: "Separate compilation" for large programs/documents.
+* one-file-many-purposes:: Using one file in several ways.
+
+
+File: literate.info, Node: on-line-form, Next: medium-scale, Prev: Glasgow-objectives, Up: Glasgow-objectives
+
+Programs/documents in an on-line form
+.....................................
+
+The people-oriented documents produced by literate-programming systems
+are usually on paper (this system provides those, too). For working
+programmers, their good properties are largely overshadowed by one
+fact: paper documents go stale quickly. Also, large programs turn into
+not-so-navigable large piles of dead trees. Surely we can do better!
+
+Note our emphasis on presenting work-in-progress, as opposed to a
+system that emphasises the presentation of the final perfect
+programming gem.
+
+Our goal is that these on-line documents should be the medium of choice
+for programmers' daily reference. (APRIL91: See the note about
+"literate Para mode" in section *Note literate-para-mode::.)
+
+Our choice for an on-line format is the GNU Info format, a primitive
+ASCII-only sort-of hypertext system. The main reason for this choice
+is to let the GNU people do as much of our programming for us as
+possible! The program `info' can display Info files on just about any
+kind of terminal; `xinfo' works with the X Window System; the
+ubiquitous GNU Emacs has an ever-improving Info mode.
+
+
+File: literate.info, Node: medium-scale, Next: language-independence, Prev: on-line-form, Up: Glasgow-objectives
+
+Programming on a medium scale
+.............................
+
+We aren't really interested in programming-in-the-small (one person, a
+few hundred lines of code), and we don't know about programming in the
+large (hundreds of programmers, millions of lines of code); our target
+audience is five-person projects working on programs the size of, say,
+a Haskell compiler :-)
+
+
+File: literate.info, Node: language-independence, Next: code-verissimilitude, Prev: medium-scale, Up: Glasgow-objectives
+
+Programming language independence
+.................................
+
+The system may be used for literate programming with any programming
+language. However, the quality of the indexing, typesetting, etc.,
+support will vary, depending on whether that language is "supported" or
+not. Fortunately, the current implementation, while clunky (see
+section *Note clunky-implementation::, makes it easy to add better
+support for a given programming language.
+
+See section *Note reordering-unemphasis:: for a related comment about
+code re-ordering.
+
+
+File: literate.info, Node: code-verissimilitude, Next: ASCII-declarative-markup, Prev: language-independence, Up: Glasgow-objectives
+
+Program code written exactly as in illiterate programs
+......................................................
+
+You put executable/compilable code into your literate programs by
+inserting it in a `\begin{code}/\end{code}' environment (or the
+"Bird-track" equivalent); for example:
+ \begin{code}
+ main _ = [ AppendChan stdout "Hello, world!\n" ]
+ \end{code}
+The principle is: you can write code inside a `\begin{code}/\end{code}'
+environment *exactly* as you would in an illiterate program in the same
+language.
+
+This brings up a dichotomy that pervades literate programs: everything
+in the program is either *code* (stuff in a code environment, or
+equivalent) or *text* (everything else).
+
+
+File: literate.info, Node: ASCII-declarative-markup, Next: hierarchical-structure, Prev: code-verissimilitude, Up: Glasgow-objectives
+
+Use of ASCII-based files, "declarative" markup
+..............................................
+
+ASCII-based files (as opposed to some weird binary "internal format"):
+so you can read the files directly and e-mail them to your friends.
+
+Insisting on ASCII files means some kind of markup commands buried in
+the text.
+
+We want the markup to be "declarative," that is, to say "what you want"
+rather than "how to produce what you want." Section numbering,
+generation of a table of contents, much indexing work, cross
+referencing, creating of the Info "node" structure, etc., etc., is done
+automagically.
+
+Our starting-point choice for a "declarative" markup notation was
+LaTeX, because that's what we know (and so do a lot of other people).
+You could make the case that GNU's Texinfo format would've been better,
+esp. given some of our other objectives. Or: you could argue that we
+should've chosen a completely different notation, because some people
+look at our literate files and think they *are* LaTeX, which they are
+not.
+
+The most important parts of our LaTeX-like notation are introduced in
+section *Note notation-tut::, and the whole mess is exhaustively
+described in section *Note Command_reference::.
+
+
+File: literate.info, Node: hierarchical-structure, Next: separate-compilation, Prev: ASCII-declarative-markup, Up: Glasgow-objectives
+
+Use of hierarchical structure
+.............................
+
+That is: programs/documents divided into sections, subsections within
+sections, subsubsections...
+
+Hierarchy is a very powerful structuring tool, but its utility for
+wading around a large sea of code is not apparent. APRIL91: See the
+comments about a "literate Para mode" in section *Note
+literate-para-mode::.
+
+See also section *Note sectioning-large-documents::.
+
+
+File: literate.info, Node: separate-compilation, Next: one-file-many-purposes, Prev: hierarchical-structure, Up: Glasgow-objectives
+
+"Separate compilation" for large programs/documents
+...................................................
+
+This really follows from the size of project we're trying to support;
+it's just *too slow* to have to slurp in the *whole* program text and
+do anything... (It's pretty slow as it is :-)
+
+Separate compilation of the embedded code: Use the normal mechanisms
+of your programming language. For example, if you have a literate C
+file, `foo.lc', then you would extract the code into `foo.c' (command:
+`lit2pgm foo.lc') and compile as normal (`gcc -c foo.c').
+
+"Separate compilation" of the (LaTeX and (Tex)info) document-generating
+tasks: this is harder and quite a lot of work *has* to be done at "link
+time". What happens: the initial "separate compilations" of all the
+individual files in a program/document (e.g., `lit2texi -c foo.lc' or
+`lit2latex -c foo.lc') produce intermediate files (`*.itxi' and
+`*.itex' files, respectively). These are then consulted when a "link"
+is done (e.g., `lit2latex root.lit', where `root.lit' `\inputs' the
+other files).
+
+(It's complicated: use Makefiles!)
+
+
+File: literate.info, Node: one-file-many-purposes, Prev: separate-compilation, Up: Glasgow-objectives
+
+Using one file in several ways
+..............................
+
+Say you're writing a Haskell compiler :-), which includes the source
+code for a typechecker. On the one hand, you want this to be included
+in "the book" (document) that is the whole compiler. However, you may
+also want to have a "typechecker document" that is itself
+self-contained (if only because the "book" is so big). Going further:
+perhaps one module of your typechecker is so amazing that you want to
+publish it as a paper.
+
+You could make copies of files, edit them, etc., but that's tacky, and
+against a most deeply-held principle of literate programming: that you
+are looking at *the* source code for the program being described.
+
+As it stands, this system lets you put `\begin{onlystandalone}' and
+`\end{onlystandalone}' around pieces of your files that only apply in
+the "do this as a standalone document" case; similarly,
+`\begin{onlypartofdoc}' and `\end{onlypartofdoc}' for stuff that only
+applies in the "the glorious whole" case.
+
+APRIL91: I am fairly convinced I got this *wrong* and believe that this
+stuff would be much better handled with a pseudo-"C pre-preprocessor"
+(one that does not look inside code blocks [see deeply-held principle
+above; section *Note code-verissimilitude::]); see section *Note
+pseudo-C-preprocessor::.
+
+
+File: literate.info, Node: Glasgow-NON-objectives, Next: Other-Glasgow-features, Prev: Glasgow-objectives, Up: Highlights
+
+NON-Objectives of our system
+----------------------------
+
+* Menu:
+
+* not-reinvent-LaTeX:: Not to reinvent LaTeX (or any other extensible notation).
+* reordering-unemphasis:: An un-emphasis on code-reordering.
+
+
+File: literate.info, Node: not-reinvent-LaTeX, Next: reordering-unemphasis, Prev: Glasgow-NON-objectives, Up: Glasgow-NON-objectives
+
+Not to reinvent LaTeX (or any other extensible notation)
+........................................................
+
+Just as with Texinfo, our markup notation has a *fixed* set of
+commands. We don't have a `\define' command that let's you define new
+macros in terms of old ones. This is for simplicity, I suppose.
+
+APRIL91: see the note about fake "C pre-processing" in section *Note
+pseudo-C-preprocessor::.
+
+
+File: literate.info, Node: reordering-unemphasis, Prev: not-reinvent-LaTeX, Up: Glasgow-NON-objectives
+
+An un-emphasis on code-reordering
+.................................
+
+Some programming languages have a narrow-minded idea about what order
+the pieces of a program must be presented (e.g., COBOL: identification
+division, then file division, then data division [how many of you knew
+this :-]), and some literate-programming systems provide lots of
+machinery to get around this orderly intransigence.
+
+We write in Haskell, which is relatively open-minded about the order in
+which functions, etc., are presented. Re-splicing together code from
+dispersed program fragments doesn't buy you much -- and we think the
+same is true for most modern or semi-modern programming languages.
+Therefore, this system has only primitive support for reordering code.
+
+
+File: literate.info, Node: Other-Glasgow-features, Next: Glasgow-NON-features, Prev: Glasgow-NON-objectives, Up: Highlights
+
+Other features of our Glasgow system
+------------------------------------
+
+* Menu:
+
+* sectioning-large-documents:: Sectioning support for large documents.
+* automatic-indexing:: Automatic indexing of your code.
+* manual-indexing:: Indexing by hand.
+* automatic-cross-referencing:: Automatic cross-referencing of your code.
+* shortcut-notations:: Shortcut notations.
+* TeX-to-ASCII:: The great "LaTeX to ASCII" problem solved!.
+
+
+File: literate.info, Node: sectioning-large-documents, Next: automatic-indexing, Prev: Other-Glasgow-features, Up: Other-Glasgow-features
+
+Sectioning support for large documents
+......................................
+
+The main thing we've done here is *change* the sectioning commands (vs
+LaTeX) so it's easy to re-arrange chunks of the hierarchy. Also, a
+default Info "node" structure is worked out, based on the sectioning
+information. (Veteran Texinfo hackers will appreciate the joys of not
+typing error-prone `@menu's.)
+
+Sectioning in an individual file should *always* begins at `\section';
+such files should then glued together in a "root file" with `\input'
+commands interspersed with `\upsection' and `\downsection' commands.
+`lit2latex'/`lit2texi' combine your files, putting appropriate
+real-LaTeX/Texinfo sectioning commands (`\part', `\chapter', etc.) in
+the right places.
+
+A side-effect of diverging from LaTeX sectioning is that we can support
+deeper nesting of sectioning commands.
+
+It's also neat to be able to change your mind about whether you want to
+start with (LaTeX-speak...) parts, chapters, sections, or whatever...
+
+Please see section *Note Sectioning:: for further details about this
+whole mess.
+
+
+File: literate.info, Node: automatic-indexing, Next: manual-indexing, Prev: sectioning-large-documents, Up: Other-Glasgow-features
+
+Automatic indexing of your code
+...............................
+
+An attempt is made to index all the "interesting things" in the code
+parts of your program. The success of this enterprise depends on the
+degree to which the language you are using is supported.
+
+In a paper manifestation, you'll get nice neat indexes, like we're used
+to. In an on-line manifestation, you would like to use the information
+to "point and jump" (our Info-based implementation does this, perhaps
+clumsily).
+
+APRIL91: See section *Note multiple-indexes:: for latest thoughts about
+indexing. Also, I've put some comment about free-text retrieval in
+section *Note free-text-index::.
+
+
+File: literate.info, Node: manual-indexing, Next: automatic-cross-referencing, Prev: automatic-indexing, Up: Other-Glasgow-features
+
+Indexing by hand
+................
+
+Indexing your text (vs your code) is not automatic. You do it by hand
+with `\index{<stuff>}' commands. The format of the `\index' commands
+is a simplified (?) form of `makeindex' commands. Section *Note
+Indexing:: gives the details.
+
+
+File: literate.info, Node: automatic-cross-referencing, Next: shortcut-notations, Prev: manual-indexing, Up: Other-Glasgow-features
+
+Automatic cross-referencing of your code
+........................................
+
+Your code may also be automatically cross-referenced; again, it's based
+on finding "interesting things" in your code; furthermore, it depends
+on distinguishing between "definitions" and "uses", because the main
+purpose of cross-referencing is to let you move quickly from a "use"
+(e.g., of a function) to its "definition".
+
+APRIL91: Sometimes you would really like to be able to go from a
+definition to all of its uses. Perhaps this should be an option.
+
+Cross-referencing is automatically OFF when producing LaTeX documents
+(we found it mainly cluttered) and ON when producing Info files (which
+lets you jump to the definitions through a node's menu).
+
+
+File: literate.info, Node: shortcut-notations, Next: TeX-to-ASCII, Prev: automatic-cross-referencing, Up: Other-Glasgow-features
+
+Shortcut notations
+..................
+
+Within non-code parts of documents, code snippets may be included
+between `at' signs; e.g., `@f x y = y@' -- appropriate formatting,
+indexing, etc., will be done.
+
+APRIL91 COMMENT: I need to clarify the proper use of these `@'s. I
+also need to figure what to do when `@'s are not the right thing! (I
+think Texinfo has an over-proliferation of commands for marking off
+this and that in the text.) See section *Note
+code-in-text-formatting::.
+
+For the ordinary text to be shown in a typewriter font (much used in
+user's guides, for example), you may use the `\tr{<text>}' command; the
+only restriction on `<text>' is that braces must be balanced. The same
+trick for "plain" (roman) font is `\pl{<text>}'. [APRIL91: See section
+*Note diff-fonts-in-text:: for further thoughts about fonts in your
+text.]
+
+APRIL91: See also: section *Note BNF-grammars::.
+
+
+File: literate.info, Node: TeX-to-ASCII, Prev: shortcut-notations, Up: Other-Glasgow-features
+
+The great "LaTeX to ASCII" problem solved!
+..........................................
+
+(Well, not quite...) A literate program looks an awful lot like a
+LaTeX document. If you convert the program to an Info file, then run
+the `info2ascii' script [which I haven't written yet :-] over it,
+you'll have a quite-reasonable all-ASCII nicely-formatted version of
+your LaTeX-ish input.
+
+
+File: literate.info, Node: Glasgow-NON-features, Prev: Other-Glasgow-features, Up: Highlights
+
+Shortcomings of our system
+--------------------------
+
+* Menu:
+
+* texinfo-limits:: Limits because of the Texinfo intermediate representation.
+* clumsy-node-namespace:: Node namespace is not "neat".
+* clunky-implementation:: A clunky implementation.
+
+
+File: literate.info, Node: texinfo-limits, Next: clumsy-node-namespace, Prev: Glasgow-NON-features, Up: Glasgow-NON-features
+
+Limits because of the Texinfo intermediate representation
+.........................................................
+
+We produce our on-line viewable GNU Info files by going through their
+Texinfo format. If something cannot be represented easily in Texinfo
+(which doesn't do things not easily representable in character-only
+ASCII), it ain't in our system. This leads to the following *very
+notable* shortcomings:
+ 1. No graphics, pictures, or sound.
+
+ 2. No fancy mathematical stuff of the sort TeX/LaTeX is so good at.
+ Note: we would like to provide enough *basic* mathematical stuff
+ so you aren't hamstrung by this restriction.
+
+
+File: literate.info, Node: clumsy-node-namespace, Next: clunky-implementation, Prev: texinfo-limits, Up: Glasgow-NON-features
+
+Node namespace is not "neat"
+............................
+
+For all practical purposes, it's *your problem* to make sure that you
+don't get nodename clashes. This is really uncool.
+
+APRIL91: Some ideas for partial alleviation of making-up-nodenames
+weariness, see section *Note revised-sectioning::.
+
+Barring that, a good discipline for making up unique nodenames would be
+helpful (I haven't found one yet).
+
+
+File: literate.info, Node: clunky-implementation, Prev: clumsy-node-namespace, Up: Glasgow-NON-features
+
+A clunky implementation
+.......................
+
+The principle has been: do as little work as possible. (What do you
+expect from the proponents of lazy functional programming?)
+
+The implementation is the Perl Script From Hell, with a supporting cast
+of the Flex Program From Hell, and a whole bunch of exceedingly useful
+programs written by other people, mainly the GNU Info/Texinfo-related
+programs and `tgrind' (by Van Jacobsen). [We can pass along the source
+to all of these programs.]
+
+
+File: literate.info, Node: notation-tut, Next: Command_reference, Prev: Highlights, Up: Top
+
+A LaTeX-like document markup language (tutorial-ish)
+====================================================
+
+Here is a simple silly literate Haskell program:
+
+ \documentstyle[literate]{report}
+ \rootsectiontype{\part}
+ \begin{document}
+ Here is my \Haskell{} program to send a message to my friends:
+ \begin{code}
+ main _ = [ AppendChan stdout (message ++ " to " ++ my_friends) ]
+ \end{code}
+
+ \section[message]{The Message}
+ \begin{code}
+ message = "Hello"
+ \end{code}
+ \subsection{Comments about the message and its implementation}
+ \begin{enumerate}
+ \item
+ The message is given as a top-level pattern binding.
+ \item
+ The @message@ binding does not violate the monomorphic restriction;
+ its type is \tr{[Char]}, which is not overloaded.
+ \end{enumerate}
+
+ \section[friends]{My friends}
+
+ \begin{code}
+ my_friends = ( \ y -> "Bob and Joe" ) 3
+ \end{code}
+
+ \printindex
+ \end{document}
+
+Here are some things to see in this example (don't worry if it doesn't
+make sense first time):
+ * The compilable program (the parts between `\begin{code}'s and
+ `\end{code}'s) is simply contained in marked-off parts of your
+ document, and the code therein is completely ordinary (no special
+ programming notation).
+
+ Such *code* is one "kind of stuff" in your literate program;
+ *text* is the other.
+
+ * The overall document is arranged hierarchically (`\section',
+ `\subsection', etc.) and looks an awful lot like a LaTeX document.
+
+ * There is quite a bit about *what* makes up your document
+ (sections, code, enumerated lists) and very little about *how*
+ your document should be formatted (e.g., "skip 2 lines"). This is
+ "declarative" markup.
+
+ * Your program code will be indexed automatically; the `\printindex'
+ command is how you say where you want the index included.
+
+ * You can refer to things-in-your-code in the text parts of your
+ document, by enclosing the reference in `@''s, as in `@message@'.
+ The reference will be suitably indexed.
+
+ * The sectioning commands (e.g., `\section') are odd (if you are
+ used to LaTeX). Most important, a sectioning command gives a
+ *relative* position in the hierarchy; this means that commands like
+ `\rootsectiontype' can be used to adjust the absolute sectioning in
+ the final document. In this example, the topmost section would be
+ a LaTeX `\chapter' by default, but it's been changed to be a
+ `\part'.
+
+ * More not-LaTeX trivia: the optional argument to `\section' serves
+ both as a label name (for `\ref', etc.) and as a node name for GNU
+ Info files.
+
+The following sections describe the more interesting parts of our
+LaTeX-like notation, illustrated in the example above. (Before that is
+a micro-tutorial on LaTeX conventions, in section *Note micro-latex::.)
+ * As the example above showed, the sectioning commands diverge quite
+ significantly from LaTeX. Section *Note Sectioning:: gives the
+ full details about sectioning.
+
+ * The example shows how program code is included in a document in the
+ simplest way: just begin `\begin{code}' and `\end{code}' around it.
+ Section *Note code-in-doc:: describes the more involved uses of
+ this feature.
+
+ * Section *Note Cross_references:: and Section *Note Indexing::
+ describe how to take full advantage of the cross-referencing and
+ indexing facilities in your literate programs.
+
+ * Section *Note Examples:: is supposed to include several complete
+ examples of literate programs but IT IS NOT FINISHED YET.
+
+Remember: Section *Note Command_reference:: is (supposed to be) a
+complete reference document about the LaTeX-like commands you may
+safely use.
+
+* Menu:
+
+* micro-latex:: A micro-tutorial on our LaTeX-like conventions.
+* Sectioning:: Sectioning commands.
+* code-in-doc:: Including program code in your document.
+* Cross_references:: Cross-referencing.
+* Indexing:: Indexing.
+* Examples:: Some complete examples [NOT FINISHED].
+* Shortcuts:: Helpful short-cut notations.
+
+
+File: literate.info, Node: micro-latex, Next: Sectioning, Prev: notation-tut, Up: notation-tut
+
+A micro-tutorial on our LaTeX-like conventions
+----------------------------------------------
+
+LaTeX is a document preparation system (described in a book of almost
+that name, by Leslie Lamport), and its notation is the basis of that
+used in this literate programming system. Unsurprisingly, one thing you
+can do with your literate programs is turn them into real LaTeX
+documents (for typesetting), using the program `lit2latex'.
+
+A few things to know about our literate-programming markup notation:
+ * Backslash (`\') is the starts-a-command character. Therefore,
+ `\item' and `\/' are commands, but `dog' and `(+)' are just plain
+ text.
+
+ * *Mandatory* arguments to a command are given inside curly braces.
+ So, we would use `\foo{bar}' to pass one argument to the command
+ `\foo'; we would use `\bar{hey1}{hey2}' to pass two arguments to
+ the command `\bar'.
+
+ * *Optional* arguments to a command are given in square brackets and
+ come before mandatory arguments. So, for example,
+ `\help[everyone]{lunch}' passes one optional and one mandatory
+ argument to the command `\help'.
+
+ * `\foo' is a *command* called "foo", while `\begin{foo}'
+ <text in-between> `\end{foo}' is an *environment* called "foo"
+ with <text in-between> being inside that environment.
+
+ * The above isn't everything you need to know.
+
+
+File: literate.info, Node: Sectioning, Next: code-in-doc, Prev: micro-latex, Up: notation-tut
+
+Sectioning commands
+-------------------
+
+[APRIL91: After you read this, you may want to see some proposed
+changes in section *Note revised-sectioning::.]
+
+* Menu:
+
+* section<n>:: The `\section<n>' command.
+* How_to_section:: How to use `\section<n>'.
+* sectiontype-and-ref:: The `\sectiontype' and `\sectionref' commands.
+* Node_specifications:: GNU Info node specifications with `\section<n>'.
+
+
+File: literate.info, Node: section<n>, Next: How_to_section, Prev: Sectioning, Up: Sectioning
+
+The `\section<n>' command
+.........................
+
+There is really just one sectioning command:
+ \section<n>[Info-node-name]{Section heading}
+where `<n>' is a positive integer, the sectioning depth. For example,
+you might have:
+ \documentstyle[literate]{book}
+ \rootsectiontype{\chapter}
+ \begin{document}
+ \section1[Node-1]{The top}
+
+ \section2[Node-2]{The next level}
+ \section3[Node-3]{The bottom level}
+ \section3[Node-4]{More on the bottom level}
+
+ \section2[Node-5]{Second part of the middle level}
+ \section3[Node-6]{Bottom level, next section}
+ \section3[Node-7]{Last section on bottom level}
+ \end{document}
+As a convenience, the following synonyms are supported:
+ \section \section1
+ \subsection \section2
+ \subsubsection \section3
+ \subsubsubsection \section4
+
+Saying `\rootsectiontype{\chapter}' causes `\section1', `\section2',
+and `\section3' to be translated into the LaTeX/Texinfo commands
+`\chapter', `\section', and `\subsection', respectively. This system
+supports deeper section nesting than LaTeX (12 levels vs. 7).
+
+If you want a section heading but don't want anything to appear in the
+table of contents, put a `*' after the command name (just like LaTeX);
+for example:
+ \subsection*[\pageref]{\pl{\pageref{<label-or-node-name>}}}
+
+If you want something that looks like a section heading but really
+isn't (no table-of-contents entry, no Info node), you probably want the
+`\heading{<title>}' command.
+
+[Support your local creaky implementation: you must put sectioning
+commands on lines of their own.]
+
+In making an Info file, the hierarchy of `\section<n>' commands will be
+turned into a corresponding hierarchy of Info nodes. With `info', you
+navigate along one level of the hierarchy with `Next'- and `Prev'-node
+links; you move up the hierarchy with `Up'-node links; and you move
+down the hierarchy (e.g., from a `\section<n>' to its `\section<n+1>'s)
+by choosing from an (automatically-generated) Info menu.
+
+
+File: literate.info, Node: How_to_section, Next: sectiontype-and-ref, Prev: section<n>, Up: Sectioning
+
+How to use `\section<n>'
+........................
+
+The presumption is that *every file in a literate document will begin
+its sectioning with a `\section'* (equivalently, `\section1') and
+further sectioning will reflect a reasonable hierarchical structure
+*within* the file. You usually know this when you are typing in a
+particular file.
+
+What you often do *not* know is how the file fits into the larger
+document, and it is most annoying (as happens sometimes with LaTeX) to
+have to rename all `\chapter's to `\section's, or some such. The
+information on how things go together is usually in a "root file,"
+which sticks things together with `\input', `\downsection' and
+`\upsection'; this example is typical:
+ \section[Desugar_match]{@match@: compiling out pattern-matching}
+ \downsection
+ % each of the following files would start with a \section
+ \input{Match.lhs}
+ \input{DeTwiddle.lhs}
+ \input{MatchCon.lhs}
+ \input{MatchLit.lhs}
+ \upsection
+
+The `\upsection's and `\downsection's determine what actual
+LaTeX/Texinfo sectioning command is generated for a particular
+`\section<n>' command. Unfortunately, the desired LaTeX/Texinfo
+sectioning command for the *top* section in your hierarchy depends on
+the kind of document you are producing. For example, should it be a
+`\part' or a `\chapter'? The solution here is to let you choose, with
+the `\rootsectiontype{\foo}' command. It says that `\section1's at the
+"top level" should be typeset as LaTeX/Texinfo `\foo''s. The defaults
+based on the `\documentstyle' should usually be adequate:
+ \documentstyle \rootsectiontype
+
+ article \section
+ report \chapter
+ book \chapter
+For a report, a useful variant might be `\rootsectiontype{\part}'.
+
+
+File: literate.info, Node: sectiontype-and-ref, Next: Node_specifications, Prev: How_to_section, Up: Sectioning
+
+The `\sectiontype' and `\sectionref' commands
+.............................................
+
+Another annoying thing with LaTeX sectioning is to type
+`Section~\ref{foo}' only to have `foo' turn out to be a "chapter" (not
+a "section"). In this system, you can type `\sectiontype{Node-name}'
+and the type of the sectioning command at node `Node-name' (e.g.,
+"chapter," "section") will be inserted [any unit below sections will be
+called "section"]. To have the inserted text be capitalised, use
+`\Sectiontype{Node-name}'.
+
+For the common idiom, `\sectiontype{Node-name}~\ref{Node-name}', you
+may use `\sectionref{Node-name}' (similarly for `\Sectionref'). [I use
+this all the time. --WDP]
+
+
+File: literate.info, Node: Node_specifications, Prev: sectiontype-and-ref, Up: Sectioning
+
+GNU Info node specifications with `\section<n>'
+...............................................
+
+[APRIL91: Don't overlook the new ideas in section *Note
+revised-sectioning::.]
+
+When making an on-line Info document from a literate program, the text
+between two sectioning commands is turned into an Info node. Moreover,
+the sectioning commands are used to determine how the nodes should be
+linked together -- almost always in the hierarchical structure implied
+by the sectioning. However, you can tweak the process as much as you
+wish (almost no-one ever wishes...).
+
+Each `\section<n>' command may have an optional "node specification",
+with which you may specify the name of the Info node and how it should
+be linked to other nodes. For common practice, I recommend giving a
+(unique) node name and enjoying the default links; for example:
+ \section[Foo-Sem]{Foo Semantics}
+Besides serving as the node name, `Foo-Sem' will also be a LaTeX
+`\label' and may be `\ref''d or `\pageref''d: for example, you could
+say, "The semantics are given in section~\ref{Foo_Sem}". (This is more
+likely to work than introducing a `\label' of your own and `\ref''ing
+that.)
+
+Node names must not contain commas (and other unpleasant characters I
+don't want to think about) and spaces are probably asking for trouble.
+
+The next example shows the *general* form for a node specification, in
+which you want to specify all of a node's links by hand:(1)
+ \section1[This-Node,Next-Node,Prev-Node,Up-Node]{Bar Semantics}
+
+A `?' may be given for any of the four node-names; then the default is
+used:
+ 1. The default node-name is the section number.
+
+ 2. The default next-node is the one associated with the next
+ same-level sectioning command (i.e., the next `\section<n>'
+ command if this is a `\section<n>' command.
+
+ 3. Analogously for the default previous-node...
+
+ 4. The default up-node is the last-seen next-level-up sectioning
+ command, e.g., if at a `\section<n>', then the last
+ `\section<n-1>' command seen.
+ Any text before the first `\section' command goes in node `Top',
+which has node specification "`Top,,,(dir)'".
+
+The recommended form `\section[Foo-Sem]{Foo Semantics}' is just short
+for `\section1[Foo-Sem,?,?,?]{Foo Semantics}'.
+
+Additional Info nodes that are unrelated to sectioning commands may be
+added with the `\node' command. [Note: not well tested.]
+
+If you want a LaTeX-style sectioning command (e.g., to specify a
+table-of-contents entry), use `onlyinfo' and `onlylatex' environments.
+
+---------- Footnotes ----------
+
+(1) Ignore the rest of this section unless you enjoy pain -- it
+presumes some familiarity with Texinfo/Info specifics; see `info info'
+and/or `info texinfo'.
+
+
+File: literate.info, Node: code-in-doc, Next: Cross_references, Prev: Sectioning, Up: notation-tut
+
+Including program code in your document
+---------------------------------------
+
+Central to literate programming is having program code in your document
+that can be directly extracted and compiled/executed.
+
+* Menu:
+
+* usual-code-in-doc:: The usual ways to put code in a documents.
+* ribbons-details:: Code ribbons: the fancy stuff.
+* reordering-with-insertribbon:: Code reordering with `\insertribbon'.
+* pseudocode:: Stuff that looks like code but isn't.
+* magic-things-in-code:: Magic things you can put in your code.
+
+
+File: literate.info, Node: usual-code-in-doc, Next: ribbons-details, Prev: code-in-doc, Up: code-in-doc
+
+The usual ways to put code in a documents
+.........................................
+
+The most straightforward way to do this is to put all the code in a
+file in one or more `\begin{code}' ... `\end{code}' environments -- the
+code can then be extracted (in the order it appears in the text) and
+fed to your favourite compiler/interpreter/whatever.
+
+An equivalent notation preferred by some is "Bird tracks", so-called
+because it started with Richard Bird (and because Cordy calls them
+that); lines starting with a `>' are extracted; for example:
+ >main _ = [AppendChan stdout "hello, world\n"]
+is equivalent to:
+ \begin{code}
+ main _ = [AppendChan stdout "hello, world\n"]
+ \end{code}
+A block of Bird-tracked code lines must have a blank line before and
+after (not having one usually indicates a typo).
+
+ COMMENT:----------------------
+
+ ToDo: Simon wants to know how code looks in (a) a LaTeX'd document
+ and (b) an Info'd document. ------------------------------
+
+
+File: literate.info, Node: ribbons-details, Next: reordering-with-insertribbon, Prev: usual-code-in-doc, Up: code-in-doc
+
+Code ribbons: the fancy stuff
+.............................
+
+Both of the above are shorthand notation for messier stuff going on
+underneath... Strictly speaking, the code in a particular document is
+made up of one or more *ribbons* of code. For example,
+ A common thing to say to the world is ``Hello, world!''
+ \begin{code}[hello-goodbye]
+ void HELLO() { printf("HELLO, WORLD!\n"); }
+ \end{code}
+
+ However, you might want to be less exuberant:
+ \begin{code}[wimp]
+ void hello() { printf("hello, world!\n"); }
+ \end{code}
+
+ And perhaps you are trying to tune out, not tune in.
+ \begin{code}[hello-goodbye]
+ void goodbye() { printf("Good-bye, cruel world...\n"); }
+ \end{code}
+
+As always, code to be extracted goes inside a
+`\begin{code}'...`\end{code}'; the *optional* argument after
+`\begin{code}' is the name of the code-ribbon to which the program-text
+belongs. The example above has two ribbons, `hello-goodbye' and
+`wimp'. You can extract any code-ribbon(s) you wish [see `lit2pgm''s
+-r option]; the disjoint pieces of a particular ribbon (e.g.,
+`hello-goodbye' above) are catenated together in the order seen.
+
+Usually, this ribbon-business is just a bother, so there is the good
+ol' default ribbon, `main'. For example, the
+way-you-normally-write-things:
+ \begin{code}
+ void adieu() { printf("Adieu, cruel world...\n"); }
+ \end{code}
+is actually short for:
+ \begin{code}[main]
+ void adieu() { printf("Adieu, cruel world...\n"); }
+ \end{code}
+
+Unsurprisingly, `main' is the default code-ribbon when one is in the
+ribbon-extraction business. Similarly, code included with `>' signs in
+the leftmost column ("Bird tracks") is just tacked onto the `main'
+ribbon, too:
+ >void
+ >adieu()
+ >{ printf("Adieu, cruel world...\n"); }
+
+
+File: literate.info, Node: reordering-with-insertribbon, Next: pseudocode, Prev: ribbons-details, Up: code-in-doc
+
+Code reordering with `\insertribbon'
+....................................
+
+If you are feeling particularly notorious, one piece of code may be
+appended to several ribbons (a comma-separated list of ribbon names,
+please -- spaces are significant except for beside the commas):
+ \begin{code}[ribbon1, ribbon2, ribbon3]
+ void adieu() { printf("Bon soir, cru\\'el world...\n"); }
+ \end{code}
+
+To get the effect of WEB-like parameterless macros, one ribbon may use
+`\insertribbon' to include a copy of another one, as in:
+ \begin{code}
+ void adieu()
+ \insertribbon{message}
+ \end{code}
+
+ \begin{code}[message]
+ { printf("Adieu, cruel world...\n"); }
+ \end{code}
+
+ToDo: CHANGE `\insertribbon' SO IT'S OUTSIDE OF code ENVIRONMENT.
+
+I don't recommend `\insertribbon'. You can make a terrible mess with
+it. I haven't tested it for months.
+
+
+File: literate.info, Node: pseudocode, Next: magic-things-in-code, Prev: reordering-with-insertribbon, Up: code-in-doc
+
+Stuff that looks like code but isn't
+....................................
+
+If you want to include alternate versions of code (for illustrative
+purposes, presumably), to be typeset as code but *not* subject to
+extraction by `lit2pgm', put the extra versions in `pseudocode'
+environments.
+
+
+File: literate.info, Node: magic-things-in-code, Prev: pseudocode, Up: code-in-doc
+
+Magic things you can put in your code
+.....................................
+
+Generally speaking, you enter your program code inside a `code'
+environment *exactly* as you would otherwise (the principle discussed in
+section *Note code-verissimilitude::), and it will appear in your
+documents as shown (nicely typeset, we hope). There are two magic
+things that you can put in your code that do not appear in your
+document (directly):
+Index entries:
+ Code is automagically indexed, but you may wish additional index
+ entries of your own choosing.
+
+Hidden comments:
+ You will sometimes want comments in your actual code that you do
+ not want printed. An example: you might want to record next to
+ each code block the names of the the test files used to exercise
+ it. This is *really boring* information to all but the most
+ dedicated reader.
+
+In both cases, the information *could* be provided outside the code
+environment (i.e., without any special construct), but it could quite
+easily get lost (code blocks can be big, even if they shouldn't be :-).
+
+In all cases, these annotations are in a form recognised as a comment
+by the compiler/whatever for that language. Please see section *Note
+Language_specific:: for the exact form used for the language you are
+interested in. A Haskell example of both magic bits might be:
+ \begin{code}
+ main _ = [AppendChan stdout "Hello, world...?\n"]
+ --idx:: world, state of
+ --hide:: use testfile093.hs
+ \end{code}
+
+[APRIL91: Yell if you really dislike (or like) these two forms of
+"magic things in code".]
+
+
+File: literate.info, Node: Cross_references, Next: Indexing, Prev: code-in-doc, Up: notation-tut
+
+Cross-referencing
+-----------------
+
+For cross-referencing, the normal thing is to use node-names on
+sectioning commands as labels, and to `\ref{<label>}' and
+`\pageref{<label>}' them, as is the LaTeX custom. `\pageref's are
+discouraged, as there is no concept of page numbers in Info files.
+
+Similarly, if you heave in a `\label{<some text>}', the Info side of
+things will assume that `<some text>' is just another label for the
+current node [NOT IMPLEMENTED (ToDo)].
+
+APRIL91: Cross-referencing is normally used to help you move from a
+*use* of a code-thing to its *definition*. There should probably be an
+option to let you get cross-referencing that will also let you move
+from a definition to all of its uses.
+
+
+File: literate.info, Node: Indexing, Next: Examples, Prev: Cross_references, Up: notation-tut
+
+Indexing
+--------
+
+[APRIL91: changes are envisaged; see section *Note multiple-indexes::.]
+
+Indexing is assumed to work with the program `makeindex', so you should
+put a a `\printindex' command where you want the index to appear
+(almost always just before `\end{document}'). (A LaTeX `\makeindex'
+command is supplied automagically before `\begin{document}'.)
+
+Roughly speaking, code portions of your document are *automatically*
+indexed, and then you index the text portion *manually*, with `\index'
+commands.
+
+`\index{<entry text>}' is the basic indexing command and offers a
+simplified `makeindex' interface.
+ * If you want just plain simple "foo" to appear in the index, use
+ `\index{foo}'.
+
+ * If you want subitems in an index entry, separate them with `!'s
+ [useful].
+
+ * If you want separate text for sorting and printing an index entry,
+ put the two texts in that order, separated by an unescaped `@'.
+
+ * To put a `!' or `@' in your index entry, escape it with a
+ backslash `\'.
+
+ * All other (semi-normal) characters work as is.
+
+I don't encourage trying to have index entries pop out in different
+fonts -- it doesn't work in plain Info files. You can write devious
+LaTeX/`makeindex' code on your own...
+
+Code-stuff in text (stuff inside `@...@') is indexed automatically,
+just like "real code". What actually happens depends on the support
+for your programming language -- section *Note Language_specific:: gives
+all the language-specific indexing idiosyncracies. The *default*
+bare-bones mechanism is that whitespace-free code-in-text over three
+characters long (e.g., `@typecheck@') will generate an index entry. To
+suppress automatic indexing of a piece of code-in-text, put a
+`\noindex' immediately following, as in `@typecheck@\noindex'.
+
+As mentioned in section *Note magic-things-in-code::, you can add index
+entries for your code by inserting specially-formatted comments (this
+depends on how well your programming language is supported). For
+example, for Haskell, you might use [NB: NOT IMPLEMENTED YET (ToDo?)]:
+ f x y z = (y z) x
+ -- the next line is a comment that will cause an index entry
+ -- equivalent to: \index{foo-bar-baz}
+ --#idx::foo-bar-baz
+
+For a chunk of code, a mini-index pointing to the definitions of the
+things it refers to (one possible definition of "things:" top-level
+functions) will be produced right after the code. (For the Info file,
+as part of the menu for that node.)
+ COMMENT:----------------------
+
+ The Info part is done; I'm still thinking about what should be done
+ for LaTeX. ------------------------------
+[APRIL91: this is one of the things contemplated in section *Note
+multiple-indexes::.]
+
+At least some provision has been made for "stop lists" for the
+automagical indexing (I'm not sure how well it works...). You put
+words/strings that are normally picked up by the indexing into a file,
+then tell the system this is your "stop list file" (`-s' option, I
+think), meaning "Don't index these things -- I'm not interested."
+
+
+File: literate.info, Node: Examples, Next: Shortcuts, Prev: Indexing, Up: notation-tut
+
+Some complete examples [NOT FINISHED]
+-------------------------------------
+
+NOT FINISHED YET. Some day...
+
+Meanwhile, you will find some reasonable not-over-huge examples in the
+`literate/tests' directory in the source.
+
+* Menu:
+
+* Simple_example:: A simple example.
+* Typical_example:: A typical example.
+* Hairy_example:: A hairy example.
+
+
+File: literate.info, Node: Simple_example, Next: Typical_example, Prev: Examples, Up: Examples
+
+A simple example
+................
+
+
+File: literate.info, Node: Typical_example, Next: Hairy_example, Prev: Simple_example, Up: Examples
+
+A typical example
+.................
+
+
+File: literate.info, Node: Hairy_example, Prev: Typical_example, Up: Examples
+
+A hairy example
+...............
+
+
+File: literate.info, Node: Shortcuts, Prev: Examples, Up: notation-tut
+
+Helpful short-cut notations
+---------------------------
+
+APRIL91: There is discussion about these sorts of things scattered
+through the "new ideas" in section *Note april91-new-ideas::.
+
+* Menu:
+
+* code-in-text:: Referring to code things in your text.
+* fonts-in-text:: Using different "fonts" in your text.
+
+
+File: literate.info, Node: code-in-text, Next: fonts-in-text, Prev: Shortcuts, Up: Shortcuts
+
+Referring to code things in your text
+.....................................
+
+In the text part of a literate program, one often wishes to refer to
+things in the code (e.g., function names) or have code expressions in
+the running text, and so forth. One would like this code-in-text to be
+typeset just like the real-code-parts (currently verbatim, but that
+could change). To mark off code-in-text, surround it with `at' signs:
+as in `@code in text@'; to put an `at' sign in in-line code, you've got
+to put in two `ats': `@x @@ (y, z)@'. Line-breaks are prevented inside
+"attified" code-text.
+
+Because things inside `at' signs are so often just what you want to be
+indexed, the rule is: if the at-signed thing contains no whitespace, an
+index entry is generated. (How to prevent indexing and how to do
+fancier things about indexing and cross-referencing are given section
+*Note Indexing::.)
+
+APRIL91: see comments in section *Note text-in-code::.
+
+
+File: literate.info, Node: fonts-in-text, Prev: code-in-text, Up: Shortcuts
+
+Using different "fonts" in your text
+....................................
+
+[APRIL91: Be sure to see section *Note diff-fonts-in-text::.]
+
+The `\tr{<text>}' command sets `<text>' in typewriter font, with no
+need for escape characters or anything -- provided the braces nest
+properly.
+
+The same trick using a "plain" (roman) font is `\pl{<text>}', to
+produce <text>.
+
+
+File: literate.info, Node: Command_reference, Next: Language_specific, Prev: notation-tut, Up: Top
+
+LaTeX-like markup commands: reference
+=====================================
+
+This section assumes you are familiar with the tutorial-ish material in
+section *Note notation-tut::. It also assumes some familiarity with
+LaTeX, in that I may say say, "It works as in LaTeX".
+
+The lists below catalog the environments (`\begin{...}/\end{...}'
+things) and commands (backslashed `\things') of our Glasgow
+literate-programming notation. [For this clunky implementation, the
+`\begin{...}' and `\end{...}' delimiters should be on lines by
+themselves, beginning in the leftmost column.]
+
+Occasional mention is made of the main programs used to process
+literate files: `lit2pgm', which extracts the code from a file;
+`lit2latex', which creates real LaTeX source from a file; and
+`lit2texi', which creates Texinfo source from a file (from which Info
+files can be made with `makeinfo').
+
+Little things first:
+ * In text, you should use the TeX style of double quotes: ```foo'''.
+
+ * In text, backslashed magic characters, e.g., `\& \_ \# \$', will
+ produce the self-same de-backslashed magic characters in the
+ output.
+
+ * Accents on characters (e.g., `\'e') are fine; they are tossed from
+ Info files.
+
+ * You may safely use the italic correction `\/'.
+
+ * At least the font-fiddling declarations `\sc' and `\tt' will work;
+ they are heartily unrecommended. APRIL91: see the comments in
+ section *Note diff-fonts-in-text::. Also, make them commands, not
+ declarations?
+
+Commands and environments (in alphabetical order):
+
+* Menu:
+
+* \appendix:: \appendix.
+* \author:: \author{<text>}.
+* center_environment:: center environment.
+* \centerline:: \centerline{<text>}.
+* \caption:: \caption{<text>}.
+* \clearpage-etc:: \clearpage and \cleardoublepage.
+* code_environment:: code environment.
+* comment_environment:: comment environment.
+* \date:: \date{<text>}.
+* \define:: \define{<command>}{<replacement>}.
+* description_environment:: description environment.
+* display_environment:: display environment.
+* \documentstyle:: \documentstyle[<style-options>]{<doc-type>}.
+* \em:: {\em <text>}.
+* enumerate_environment:: enumerate environment.
+* figure_environment:: figure environment.
+* flushdisplay_environment:: flushdisplay environment.
+* flushverbatim_environment:: flushverbatim environment.
+* \footnote:: \footnote{<text>}.
+* \heading:: \heading{<title>}.
+* \index:: \index{<entry>}.
+* \input:: \input{<filename>}.
+* \inputnow:: \inputnow{<filename>}.
+* \insertribbon:: \insertribbon{<ribbon-name>}.
+* itemize_environment:: itemize environment.
+* \label:: \label.
+* \listoffigures-etc:: \listoffigures and \listoftables.
+* \makeindex:: \makeindex.
+* \maketitle:: \maketitle.
+* menu_environment:: menu environment.
+* \menuentry:: \menuentry{<tag>}{<description>}.
+* \node:: \node{<node-spec>}.
+* \pounds:: \pounds<something-like-a-number>.
+* onlyinfo_environment:: onlyinfo environment.
+* onlylatex_environment:: onlylatex environment.
+* onlypartofdoc_environment:: onlypartofdoc environment.
+* onlystandalone_environment:: onlystandalone environment.
+* \pageref:: \pageref{<label-or-node-name>}.
+* \pl:: \pl.
+* \printindex:: \printindex.
+* pseudocode_environment:: pseudocode environment.
+* quotation_environment:: quotation environment.
+* rawlatex_environment:: rawlatex environment.
+* \ref:: \ref{<label-or-node-name>}.
+* \rootsectiontype:: \rootsectiontype{<real-sectioning-command>}.
+* \sectiontype:: \sectiontype{<nodename>}.
+* \sectionref:: \sectionref{<nodename>}.
+* \standaloneornot:: \standaloneornot{<ifso>}{<ifnot>}.
+* \suppresscomments:: \suppresscomments.
+* table_environment:: table environment.
+* \tableofcontents:: \tableofcontents.
+* tabular_environment:: tabular environment.
+* \title:: \title{<text>}.
+* \tr:: \tr.
+* verbatim_environment:: verbatim environment.
+
+
+File: literate.info, Node: \appendix, Next: \author, Prev: Command_reference, Up: Command_reference
+
+ \appendix
+
+Section numbering after this command is for appendices. (Has no effect
+on Info files. ToDo: it probably should.)
+
+
+File: literate.info, Node: \author, Next: center_environment, Prev: \appendix, Up: Command_reference
+
+ \author{<text>}
+
+Please see under `\maketitle'.
+
+
+File: literate.info, Node: center_environment, Next: \centerline, Prev: \author, Up: Command_reference
+
+ center environment
+
+As for LaTeX. [APRIL91: Not implemented (and not sure how to do it
+easily on the Texinfo side), but I need to do something because Simon
+keeps using it.]
+
+
+File: literate.info, Node: \centerline, Next: \caption, Prev: center_environment, Up: Command_reference
+
+ \centerline{<text>}
+
+As for LaTeX.
+
+
+File: literate.info, Node: \caption, Next: \clearpage-etc, Prev: \centerline, Up: Command_reference
+
+ \caption{<text>}
+
+As for LaTeX; likely to be unsatisfactory for Info files because the
+latter doesn't do figures.
+
+
+File: literate.info, Node: \clearpage-etc, Next: code_environment, Prev: \caption, Up: Command_reference
+
+ \clearpage and \cleardoublepage
+
+As in LaTeX; no effect on Info files.
+
+
+File: literate.info, Node: code_environment, Next: comment_environment, Prev: \clearpage-etc, Up: Command_reference
+
+ code environment
+
+See section *Note code-in-doc::. Also, don't forget the `pseudocode'
+environment.
+
+You cannot nest other environments inside code environments.
+
+
+File: literate.info, Node: comment_environment, Next: \date, Prev: code_environment, Up: Command_reference
+
+ comment environment
+
+Text in a `comment' environment will be output (perhaps with extra
+indentation, smaller font, etc.) if a `\suppresscomments' command
+hasn't yet been encountered. [NB: `\suppresscomments' doesn't work
+with `lit2texi'.]
+
+A comment environment cannot include another comment environment.
+
+
+File: literate.info, Node: \date, Next: \define, Prev: comment_environment, Up: Command_reference
+
+ \date{<text>}
+
+As for LaTeX; please see under `\maketitle' for exact details.
+
+
+File: literate.info, Node: \define, Next: description_environment, Prev: \date, Up: Command_reference
+
+ \define{<command>}{<replacement>}
+
+Ultra-simple macro substitution, NOT LIKE LaTeX. The text for
+`<command>' will be replaced with `<replacement>'; no nesting, no funny
+characters, nothing fancy. Don't `\define' the same `<command>' twice,
+for example. Intended for customising documents; please see the note
+under `\input'.
+
+Defaults are provided for `Haskell', `LaTeX', `TeX' and `...'. More
+defaults on request.
+
+APRIL91: see section *Note pseudo-C-preprocessor:: for what I would
+REALLY like to do about "defining".
+
+
+File: literate.info, Node: description_environment, Next: display_environment, Prev: \define, Up: Command_reference
+
+ description environment
+
+As in LaTeX.
+
+
+File: literate.info, Node: display_environment, Next: \documentstyle, Prev: description_environment, Up: Command_reference
+
+ display environment
+
+Similar to `verbatim' (line-breaks are obeyed) but formatted in the
+prevailing font (not necessarily typewriter). There is a
+`flushdisplay' environment as well.
+
+You can't nest one display environment inside another.
+
+
+File: literate.info, Node: \documentstyle, Next: \em, Prev: display_environment, Up: Command_reference
+
+ \documentstyle[<style-options>]{<doc-type>}
+
+You do not have to the `literate' LaTeX style option; e.g.,
+`\documentstyle[literate]{report}', but it is probably a good idea so
+people don't think you're writing real LaTeX.
+
+`\documentstyle' has two magical actions: (1) the type of document
+(report, article, etc.) determines the default value for
+`\rootsectiontype', and (2) it indicates that a standalone document is
+being generated (not just a part of one). [APRIL91: bear in mind that
+this standalone business is in jeopardy.]
+
+
+File: literate.info, Node: \em, Next: enumerate_environment, Prev: \documentstyle, Up: Command_reference
+
+ {\em <text>}
+
+The \em (emphasize) declaration works just as in LaTeX.
+
+APRIL91: make it a command, not a declaration, i.e., \em{<text>}?
+
+
+File: literate.info, Node: enumerate_environment, Next: figure_environment, Prev: \em, Up: Command_reference
+
+ enumerate environment
+
+As in LaTeX.
+
+
+File: literate.info, Node: figure_environment, Next: flushdisplay_environment, Prev: enumerate_environment, Up: Command_reference
+
+ figure environment
+
+Goes straight through for LaTeX; ignored for Info files, meaning that
+whatever is inside won't "float." (Remember: we don't really do
+figures; see section *Note texinfo-limits::.)
+
+
+File: literate.info, Node: flushdisplay_environment, Next: flushverbatim_environment, Prev: figure_environment, Up: Command_reference
+
+ flushdisplay environment
+
+Same as the `display' environment, except it is not indented relative
+to the left margin.
+
+You can't nest one flushdisplay environment inside another.
+
+
+File: literate.info, Node: flushverbatim_environment, Next: \footnote, Prev: flushdisplay_environment, Up: Command_reference
+
+ flushverbatim environment
+
+Same as the `verbatim' environment except that text is not indented
+relative to the left margin.
+
+You can't nest other environments inside a flushverbatim environment;
+see the note in section *Note verbatim_environment::.
+
+
+File: literate.info, Node: \footnote, Next: \heading, Prev: flushverbatim_environment, Up: Command_reference
+
+ \footnote{<text>}
+
+Footnotes work! NB: with `makeinfo', you may choose one of two ways of
+doing footnotes in an Info file. By default, they will be at the
+bottom of the node (style BN), as opposed to in a node of their own
+(style MN). [ToDo: update the makeinfo info]
+
+
+File: literate.info, Node: \heading, Next: \index, Prev: \footnote, Up: Command_reference
+
+ \heading{<title>}
+
+A pseudo-sectioning command that formats `title' as if it were a
+section heading (no numbering or any of that rot), but it doesn't put
+anything in the table of contents, no Info node, no anything weird.
+
+
+File: literate.info, Node: \index, Next: \input, Prev: \heading, Up: Command_reference
+
+ \index{<entry>}
+
+Roughly as for LaTeX with `makeindex'. Don't try anything too weird:
+for example, `\index{<mumble>}' inside a footnote doesn't work.
+Warning: full-blown `makeindex'-style indexing has been "simplified":
+please see section *Note Indexing:: for the full gory (but wonderful!)
+details.
+
+
+File: literate.info, Node: \input, Next: \inputnow, Prev: \index, Up: Command_reference
+
+ \input{<filename>}
+
+Be sure these are on lines by themselves and start in column 1. The
+argument should be the full filename -- no implied suffix. Files will
+be searched for along the `LITINPUTS' path, specified by an environment
+variable of the same name. The default path includes only your current
+working directory.
+
+`\input's are only followed at link time; if that's not what you want,
+either give the appropriate command-line flag (`-n') or use `\inputnow'.
+
+APRIL91: see section *Note pseudo-C-preprocessor:: for some thoughts
+about how inputting may be changed.
+
+
+File: literate.info, Node: \inputnow, Next: \insertribbon, Prev: \input, Up: Command_reference
+
+ \inputnow{<filename>}
+
+These are `\input's that are followed always, no matter what.
+Otherwise, they are the same.
+
+APRIL91: `\inputnow' may go away at any second.
+
+
+File: literate.info, Node: \insertribbon, Next: itemize_environment, Prev: \inputnow, Up: Command_reference
+
+ \insertribbon{<ribbon-name>}
+
+Used to insert the text of one code-ribbon into another; see section
+*Note code-in-doc::. Must share a line with nothing but whitespace.
+Not recommended.
+
+ToDo: needs to be made to work *outside* of code environments, rather
+than inside them.
+
+DOES NOT WORK WITH `lit2pgm -q'! (which is what we often use.)
+
+
+File: literate.info, Node: itemize_environment, Next: \label, Prev: \insertribbon, Up: Command_reference
+
+ itemize environment
+
+As in LaTeX. British spelling ("itemise") also accepted.
+
+
+File: literate.info, Node: \label, Next: \listoffigures-etc, Prev: itemize_environment, Up: Command_reference
+
+ \label
+
+Free-standing `\label's [supposedly] work as expected in LaTeX; in Info
+files, a `\label' is taken as just another name for the node the
+`\label' is in. Determining which node it's in doesn't take account of
+`\input's -- it's the one it "appears" to be in -- which may not be
+what you want. You *really should* use node-names as labels (see
+section *Note Node_specifications::)...
+
+Labels (and, therefore, nodenames) shouldn't have weird characters in
+them. Such labels (nodenames) will be studiously ignored.
+
+
+File: literate.info, Node: \listoffigures-etc, Next: \makeindex, Prev: \label, Up: Command_reference
+
+ \listoffigures and \listoftables
+
+As for LaTeX; has no effect on Info files, which don't do lists of
+figures or tables.
+
+
+File: literate.info, Node: \makeindex, Next: \maketitle, Prev: \listoffigures-etc, Up: Command_reference
+
+ \makeindex
+
+Not necessary even for LaTeX -- one is inserted automagically just
+before `\begin{document}'; has no effect on `lit2texi'.
+
+
+File: literate.info, Node: \maketitle, Next: menu_environment, Prev: \makeindex, Up: Command_reference
+
+ \maketitle
+
+Will work as in LaTeX for simple cases, using values provided by
+`\author{<author-stuff>}', `\title{<title-stuff>}', and
+`\date{<date-stuff>}'. The `\\' line-breaker works. You die if you
+try anything weird.
+
+For better or worse, if you use the `-g' option (to "grab" a subtree of
+text for printing), then it *does* matter if the `\maketitle' is in the
+pre-amble (before `\begin{document}') or not. Please see section *Note
+Programs-and-options:: for the sorry details.
+
+
+File: literate.info, Node: menu_environment, Next: \menuentry, Prev: \maketitle, Up: Command_reference
+
+ menu environment
+
+In producing an Info file, text in a `menu' environment is copied
+verbatim to create an Info menu. You must provide something that
+Texinfo can grok. This whole mess might be used in conjunction with
+`\suppressmenu' [if `\suppressmenu' were implemented yet].
+
+APRIL91: this should probably be nuked if the rawtexinfo environment
+comes online.
+
+
+File: literate.info, Node: \menuentry, Next: \node, Prev: menu_environment, Up: Command_reference
+
+ \menuentry{<tag>}{<description>}
+
+Requests that an extra menu entry be put at the *beginning* of this
+section's menu.
+
+
+File: literate.info, Node: \node, Next: \pounds, Prev: \menuentry, Up: Command_reference
+
+ \node{<node-spec>}
+
+(Ignored for LaTeX.) Makes an extra node in the Texinfo file; the
+`<node-spec>' is copied straight through to the output, so it's your
+problem to include something sensible.
+
+APRIL91: nuked if rawtexinfo environment comes in?
+
+
+File: literate.info, Node: \pounds, Next: onlyinfo_environment, Prev: \node, Up: Command_reference
+
+ \pounds<something-like-a-number>
+
+The \pounds must be followed by: zero or more whitespace characters, a
+digit or a question mark, zero or more
+digits/question-marks/commas/full-stops/the-letters-K-or-M, and a
+digit/question-mark/the-letter-K-or-M. The Ks or Ms may be in
+lower-case. The mind boggles.
+
+
+File: literate.info, Node: onlyinfo_environment, Next: onlylatex_environment, Prev: \pounds, Up: Command_reference
+
+ onlyinfo environment
+
+Only the Texinfo/Info extraction program(s) pay attention to stuff
+inside. Don't put code in here!
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+
+File: literate.info, Node: onlylatex_environment, Next: onlypartofdoc_environment, Prev: onlyinfo_environment, Up: Command_reference
+
+ onlylatex environment
+
+Only the LaTeX extraction program(s) pay attention to stuff inside.
+Don't put code in here!
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+
+File: literate.info, Node: onlypartofdoc_environment, Next: onlystandalone_environment, Prev: onlylatex_environment, Up: Command_reference
+
+ onlypartofdoc environment
+
+The extraction programs pay attention to stuff inside only if they
+believe this is just a piece of a document (i.e., "separate
+compilation" is going on). As always, don't put code in here! See the
+`\standaloneornot' command for a shortcut.
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+
+File: literate.info, Node: onlystandalone_environment, Next: \pageref, Prev: onlypartofdoc_environment, Up: Command_reference
+
+ onlystandalone environment
+
+The extraction programs pay attention to stuff inside only if they
+believe that a standalone document is in the works (i.e., a
+`\documentstyle' command has been seen or the `-S' flag given). As
+always, don't put code in here! See the `\standaloneornot' command for
+a shortcut.
+
+APRIL91: this stuff is in jeopardy of disappearing.
+
+
+File: literate.info, Node: \pageref, Next: \pl, Prev: onlystandalone_environment, Up: Command_reference
+
+ \pageref{<label-or-node-name>}
+
+In making LaTeX documents, works as usual. In making Info files,
+treated as a `\ref' (there is no concept of "page" in an Info document).
+
+
+File: literate.info, Node: \pl, Next: \printindex, Prev: \pageref, Up: Command_reference
+
+ \pl
+
+Plain text, set in a roman font; equivalent to `\mbox{\rm #1}', except
+that the argument can include any old printable ASCII characters,
+including properly-nested braces (escaping them is irrelevant). If you
+want to do something weird, do it another way. Note that linebreaks
+within the `\pl' are prevented.
+
+The equivalent typewriter thing is `\tr'.
+
+APRIL91: see possible changes in section *Note diff-fonts-in-text::.
+
+
+File: literate.info, Node: \printindex, Next: pseudocode_environment, Prev: \pl, Up: Command_reference
+
+ \printindex
+
+Should be just before `\end{document}'. In Info mode, generates a node
+`Index' at the same sectioning depth as your top-level sectioning
+commands.
+
+APRIL91: see possible changes in section *Note multiple-indexes::.
+
+
+File: literate.info, Node: pseudocode_environment, Next: quotation_environment, Prev: \printindex, Up: Command_reference
+
+ pseudocode environment
+
+Format the same way as in a `code' environment, but the enclosed stuff
+is not subject to extraction by `lit2pgm'.
+
+Other environments do not nest inside a pseudocode environment.
+
+
+File: literate.info, Node: quotation_environment, Next: rawlatex_environment, Prev: pseudocode_environment, Up: Command_reference
+
+ quotation environment
+
+As in LaTeX.
+
+
+File: literate.info, Node: rawlatex_environment, Next: \ref, Prev: quotation_environment, Up: Command_reference
+
+ rawlatex environment
+
+If lit2latexing, copies the body of the environment straight through.
+Otherwise, discard it.
+
+One trick you may need: because of the feeble implementation, the
+system may still try to "follow" an `\input' inside a rawlatex
+environment (which it shouldn't). The solution is to "hide" the
+`\input' so it isn't first on a line:
+ \begin{rawlatex}
+ \begin{figure}
+ {}\input{weird-fig.ps}
+ \caption{Weird Figure}
+ \end{figure}
+ \end{rawlatex}
+
+
+File: literate.info, Node: \ref, Next: \rootsectiontype, Prev: rawlatex_environment, Up: Command_reference
+
+ \ref{<label-or-node-name>}
+
+As for LaTeX.
+
+
+File: literate.info, Node: \rootsectiontype, Next: \sectiontype, Prev: \ref, Up: Command_reference
+
+ \rootsectiontype{<real-sectioning-command>}
+
+Please see section *Note Sectioning::.
+
+
+File: literate.info, Node: \sectiontype, Next: \sectionref, Prev: \rootsectiontype, Up: Command_reference
+
+ \sectiontype{<nodename>}
+
+Please see section *Note sectiontype-and-ref::.
+
+
+File: literate.info, Node: \sectionref, Next: \standaloneornot, Prev: \sectiontype, Up: Command_reference
+
+ \sectionref{<nodename>}
+
+Please see section *Note sectiontype-and-ref::.
+
+
+File: literate.info, Node: \standaloneornot, Next: \suppresscomments, Prev: \sectionref, Up: Command_reference
+
+ \standaloneornot{<ifso>}{<ifnot>}
+
+If doing standalone-document processing (i.e., a `\documentstyle' seen
+or `-S' flag given), use text `<ifso>'; otherwise, use text `<ifnot>'.
+Keep this on one line *by itself*, OK?; for longer things, use the
+`onlystandalone' and `onlypartofdoc' environments.
+
+APRIL91: this stuff is in SEVERE jeopardy of being nuked; see section
+*Note pseudo-C-preprocessor::.
+
+
+File: literate.info, Node: \suppresscomments, Next: table_environment, Prev: \standaloneornot, Up: Command_reference
+
+ \suppresscomments
+
+Best put in the preamble of your overall document (i.e., before
+`\begin{document}'). Causes text in all subsequent `comment'
+environments to be ignored. NB: only works in producing LaTeX
+documents. (ToDo: fix this)
+
+
+File: literate.info, Node: table_environment, Next: \tableofcontents, Prev: \suppresscomments, Up: Command_reference
+
+ table environment
+
+Goes straight through for LaTeX; ignored for Info files, meaning that
+whatever is inside won't "float."
+
+
+File: literate.info, Node: \tableofcontents, Next: tabular_environment, Prev: table_environment, Up: Command_reference
+
+ \tableofcontents
+
+As for LaTeX; adds extra stuff to the top-level menu in an Info file.
+
+
+File: literate.info, Node: tabular_environment, Next: \title, Prev: \tableofcontents, Up: Command_reference
+
+ tabular environment
+
+Same format as LaTeX, but anything magical beyond `&', `\\', and
+`\hline' will probably get you in trouble.
+
+Other environments don't nest inside a tabular environment.
+
+
+File: literate.info, Node: \title, Next: \tr, Prev: tabular_environment, Up: Command_reference
+
+ \title{<text>}
+
+Please see under `\maketitle'.
+
+
+File: literate.info, Node: \tr, Next: verbatim_environment, Prev: \title, Up: Command_reference
+
+ \tr
+
+Set in typewriter font; equivalent to `\mbox{\tt #1}', except that the
+argument can include any old printable ASCII characters, including
+properly-nested braces (escaping them is irrelevant). If you want to
+do something weird, do it another way. Note that linebreaks within the
+`\tr' are prevented.
+
+The equivalent non-typewriter thing is `\pl'.
+
+APRIL91: see section *Note diff-fonts-in-text:: for further comment on
+this stuff.
+
+
+File: literate.info, Node: verbatim_environment, Prev: \tr, Up: Command_reference
+
+ verbatim environment
+
+As in LaTeX -- line-breaks are obeyed and everything is in typewriter
+font. See also: the `flushverbatim' and `display' environments.
+
+You can't nest other environments inside verbatim environments. A
+trick (hack) you can use to put a verbatim environment inside another
+is to indent the inner one by one space, as in:
+ \begin{verbatim}
+ ...
+ \begin{verbatim}
+ ...
+ \end{verbatim}
+ ...
+ \end{verbatim}
+
+
+File: literate.info, Node: Language_specific, Next: Habits, Prev: Command_reference, Up: Top
+
+Language-specific processing
+============================
+
+This section describes the processing of code in documents that is done
+in a language-specific way. This is mainly to do with indexing,
+typesetting, and similar matters.
+
+First, however, we give the default rules used when the programming
+language used is unsupported or unknown.
+
+* Menu:
+
+* Default_rules:: Rules for unknown or unsupported languages.
+* Haskell_rules:: Language-specific rules for Haskell.
+* Perl_rules:: Language-specific rules for `perl'.
+* C_rules:: Language-specific rules for `C'.
+* Fortran_rules:: Language-specific rules for `FORTRAN'.
+
+
+File: literate.info, Node: Default_rules, Next: Haskell_rules, Prev: Language_specific, Up: Language_specific
+
+Rules for unknown or unsupported languages
+------------------------------------------
+
+[Not finished yet.]
+
+No hidden comments or explicit index entries in code.
+
+
+File: literate.info, Node: Haskell_rules, Next: Perl_rules, Prev: Default_rules, Up: Language_specific
+
+Language-specific rules for Haskell
+-----------------------------------
+
+[This section is not finished yet.]
+
+An explicit code index entry comment is of the form:
+`--idx::<whatever>', on a line of its own.
+
+A hidden comment is of the form: `--hide::<whatever>', on a line of its
+own.
+
+
+File: literate.info, Node: Perl_rules, Next: C_rules, Prev: Haskell_rules, Up: Language_specific
+
+Language-specific rules for `perl'
+----------------------------------
+
+[This section is not finished yet.]
+
+An explicit code index entry comment is of the form:
+`#idx::<whatever>', on a line of its own.
+
+A hidden comment is of the form: `#hide::<whatever>', on a line of its
+own.
+
+
+File: literate.info, Node: C_rules, Next: Fortran_rules, Prev: Perl_rules, Up: Language_specific
+
+Language-specific rules for `C'
+-------------------------------
+
+[This section is not finished yet.]
+
+
+File: literate.info, Node: Fortran_rules, Prev: C_rules, Up: Language_specific
+
+Language-specific rules for `FORTRAN'
+-------------------------------------
+
+[This section is not finished yet.]
+
+The FORTRAN-specific support was provided by Adriaan Joubert
+(adriaan@dcs.qmw.ac.uk).
+
+
+File: literate.info, Node: Habits, Next: Caveats, Prev: Language_specific, Up: Top
+
+A checklist of good literate habits
+===================================
+
+[Suggestions welcome. Haven't worked on this in a while.]
+
+ * Express your ideas in a way amenable to plain ASCII
+ representation, as well as that of full-blown TeX typesetting.
+ For example, serious TeX math-mode stuff is not really on (even if
+ you can get it past `lit2latex'). If you find this constraint a
+ big problem, you may well be using the wrong tool for the job.
+
+ * If you test your document first as an Info file (i.e., use
+ `lit2texi' to process it), once that is right then it is very
+ likely that the LaTeX side of things (using `lit2latex') will come
+ out right as well. The reverse is not true.
+
+ * Follow the convention that the sectioning in every file begins
+ with a `\section'. For details on how to do sectioning, please see
+ section *Note How_to_section::.
+
+ * Arrange your document so that your Info nodes come out no more than
+ two screenfuls' long. Very long nodes obviate the whole point of
+ Info documents.
+
+ * It's hard to make up good sets of Info node names. First, they
+ must be unique! Second, it's best if the uniqueness is in the
+ first few characters, so that nodename completion may be used to
+ most advantage.
+
+
+File: literate.info, Node: Caveats, Next: Programs-and-options, Prev: Habits, Up: Top
+
+Caveats: bugs and foibles
+=========================
+
+As mentioned in section *Note clunky-implementation::, the initial
+implementation of this literate-programming system is delicate at best.
+
+ 1. Environment-commands should be on lines of their own, and
+ preferably start in column 1; the latter is especially important
+ for verbatim environments.
+
+ 2. The line numbers reported with errors stand a fair chance of being
+ wrong or even laughably irrelevant. LaTeX doesn't report errors in
+ terms of their original source anyway at all... (urgh)
+
+ 3. `\Define'-itions (incl. the built-in ones for Haskell, LaTeX,
+ etc.) are expanded inside `\tr' and friends.
+
+ 4. You can get confused `\items' (in enumerations, etc.) if you have:
+ \item[... stuff here... ] ...................... ]
+ right bracket on the same line -------------------^
+ The solution (and it's better style anyway) is to put `\items' on
+ lines of their own. This is a vestige of the implementation...
+
+ 5. Don't put `\index' commands inside footnotes. There are probably
+ some other related restrictions... (ToDo)
+
+ 6. Tabs in code will be expanded to spaces. This matters only if you
+ have tabs in string constants, or some such (which you shouldn't,
+ because it's hard for the reader of your code to see what you've
+ done; use `\t' or the equivalent).
+
+ 7. If you use the cross-referencing (`-D', I think), you have the
+ annoying feature of cross-referencing to things very near by, even
+ on the same page. I don't know how to stop this.
+
+
+File: literate.info, Node: Programs-and-options, Next: Info_etc, Prev: Caveats, Up: Top
+
+Programs to process literate documents
+======================================
+
+In this incarnation, the programs `lit2pgm', `lit2latex', and
+`lit2texi' (to extract program, LaTeX, or GNU Texinfo fodder) are just
+three ways of invoking one killer `perl' script, `lit2stuff'.
+
+[Actually, this same script may be invoked as `mkdependlit', to build a
+set of `make' dependencies for a literate document, as `lit2text', to
+extract just the non-code text (perhaps for spell-checking), or as
+`lit2changelog', which is the (mainly unimplemented) interface to the
+changelog-slurping code. I ignore these details herein.]
+
+APRIL91: there are starting to be enough options that getopt-style
+one-letter names aren't enough/too obtuse. Some revision may be in
+order there... See section *Note revised-pgm-options::.
+
+For all three programs, their invocation takes the form
+`lit2<whatever> [options] [input-file]'. Usually, output is to a file
+determined from the input-file's suffix (e.g., a `.hs' file from a
+`.lhs' file); if no input file is provided or life becomes confused,
+output is to the standard output. You can control input and output
+explicitly with the `-i' and `-o' options.
+
+Known file suffixes and what they mean:
+
+ .lit a literate-document file with no code in it (e.g., this one)
+ .lhs literate Haskell source
+ .lprl literate Perl source
+ .llex literate Lex source
+ .lc literate C source
+ .lh literate C header source
+ .ltex literate TeX macros
+ .lf literate FORTRAN
+
+The suffixes `.itex' and `.itxi' indicate the intermediate files from
+"separate compilation" (to LaTeX and Texinfo, respectively) of parts of
+a larger document.
+
+In ordinary life, given a literate C program `foo' in file `foo.lc',
+one would hope that the following simple invocations would suffice:
+ lit2pgm foo.lc
+ gcc -o foo foo.c
+
+ lit2latex foo.lc
+ latex foo.tex
+
+ lit2texi foo.lc
+ makeinfo foo.texi
+ # (and if you really want to make things right, use the script...
+ postmakeinfo foo.info
+ # as well)
+
+What follows are the options to control these programs (and to
+complicate your life [and mine, too]). Not all command-line options
+make sense for all three programs; they are so noted. Options may be
+glopped together in the best getopt(3) style.
+
+* Menu:
+
+* A_option:: -A <pgm-name> option.
+* c_option:: -c option.
+* d_option:: -d option.
+* capital_D_option:: -D option.
+* f_option:: -f <nodename-suffix> option.
+* g_option:: -g <node-name> option.
+* H_option:: -H <dir1>:<dir2> option.
+* i_option:: -i <input-file> option.
+* capital_I_option:: -I <directories> option.
+* capital_L_option:: -L option.
+* l_option:: -l <language> option.
+* n_option:: -n option.
+* capital_N_option:: -N <info-filename> option.
+* o_option:: -o <output-file> option.
+* capital_O_option:: -O option.
+* p_option:: -p <pagebreak-hints> option.
+* q_option:: -q option.
+* r_option:: -r <ribbons-to-get> option.
+* s_option:: -s <stop-list-file> option.
+* capital_S_option:: -S option.
+* t_option:: -t <typesetting-hints> option.
+* v_option:: -v option.
+* x_option:: -x <xref-hints> option.
+
+
+File: literate.info, Node: A_option, Next: c_option, Prev: Programs-and-options, Up: Programs-and-options
+
+ -A <pgm-name> option
+
+(For hackers only.) Assume the program was invoked as `<pgm-name>'.
+must be the first option given. Still has to be either `lit2pgm',
+`lit2texi', or `lit2latex'.
+
+
+File: literate.info, Node: c_option, Next: d_option, Prev: A_option, Up: Programs-and-options
+
+ -c option
+
+(Not `lit2pgm'.) Produce Texinfo or LaTeX output (as appropriate) but
+don't try to "link" together with other parts of the same document.
+Think of the `-c' option to a C compiler...
+
+
+File: literate.info, Node: d_option, Next: capital_D_option, Prev: c_option, Up: Programs-and-options
+
+ -d option
+
+Print debugging information. I will be monumentally surprised if this
+is of any use to you!
+
+
+File: literate.info, Node: capital_D_option, Next: f_option, Prev: d_option, Up: Programs-and-options
+
+ -D option
+
+(`lit2latex' only.) Print cross-references to code definitions in the
+text.
+
+APRIL91: this option stands some chance of being renamed if the
+pseudo-C-preprocessor comes in; see section *Note
+pseudo-C-preprocessor::.
+
+
+File: literate.info, Node: f_option, Next: g_option, Prev: capital_D_option, Up: Programs-and-options
+
+ -f <nodename-suffix> option
+
+(`lit2texi' only.) Append the string `<nodename-suffix>' to every
+nodename in a file. This can be useful if you're trying to avoid
+nodename clashes between nodes in different parts of a big document
+(two of which might, for example, have nodes named "Introduction").
+
+APRIL91: A feeble solution; see section *Note clumsy-node-namespace::.
+
+
+File: literate.info, Node: g_option, Next: H_option, Prev: f_option, Up: Programs-and-options
+
+ -g <node-name> option
+
+(`lit2latex' only.) Grab the sub-tree of text for which node
+`<node-name>' is the root. Used when you want to print a whole chapter
+or section or something, rather than just one Info node.
+
+*At this time, this option is only suitable for printing drafts.*
+
+What is actually done: the output LaTeX-file consists of the pre-amble
+(really: everything before the first `\section' command -- not quite
+what you want), the subtree you asked for, and `\end{document}'. Your
+section will be numbered `1' no matter what.
+
+
+File: literate.info, Node: H_option, Next: i_option, Prev: g_option, Up: Programs-and-options
+
+ -H <dir1>:<dir2> option
+
+(For hackers only.) Used by villanous people to override the hardwired
+directories (`<dir1>' for platform-specific files and `<dir2>' for
+platform-independent `perl' libraries) where the literate-programming
+system finds its stuff. Also see the `-A' flag.
+
+
+File: literate.info, Node: i_option, Next: capital_I_option, Prev: H_option, Up: Programs-and-options
+
+ -i <input-file> option
+
+Specify a specific input file. If not specified with `-i', then the
+first non-option command-line argument; if no such thing, then standard
+input. You may also specify standard input as the "input file" with
+`-i -'.
+
+
+File: literate.info, Node: capital_I_option, Next: capital_L_option, Prev: i_option, Up: Programs-and-options
+
+ -I <directories> option
+
+Add (colon-separated) `<directories>' to the front of the default path
+used to follow `\input' commands (just `.' at the moment). Only give
+one `-I' option; I cannot promise what will happen if you give more
+than one.
+
+Slight magic: the `.' in the path means: first, look in the directory
+where the file doing the `\input''ing is; if not there, look in the
+current working directory. (This is usually what you want.)
+
+
+File: literate.info, Node: capital_L_option, Next: l_option, Prev: capital_I_option, Up: Programs-and-options
+
+ -L option
+
+(`lit2texi' only.) Alternate style of node linking -- puts in more
+defaults for "next" and "previous" nodes. If a node doesn't have a
+"next" ["previous"] at its level (e.g., it's the last section in a
+chapter), then its "next" ["previous"] node will be the physically-next
+[-previous] one, regardless of sectioning level. (The default is for
+such nodes to have no next [previous] node.)
+
+[I like the -L node-linking scheme but `makeinfo' issues warnings about
+it. APRIL91: newer version of some Info readers achieve the same
+effect using additional moving-around-the-tree commands.]
+
+
+File: literate.info, Node: l_option, Next: n_option, Prev: capital_L_option, Up: Programs-and-options
+
+ -l <language> option
+
+(Not `lit2pgm'.) Assume that any code in the input file is written in
+<language> and process accordingly (automatic indexing, etc.). The
+<language> is normally intuited from the input-file suffix (e.g.,
+`.lhs' suggests Haskell code). The `-x', `-p', and `-t' options may be
+used to tweak cross-referencing, page-breaking, and typesetting of
+code, respectively.
+
+
+File: literate.info, Node: n_option, Next: capital_N_option, Prev: l_option, Up: Programs-and-options
+
+ -n option
+
+Follow `\input' commands.
+
+
+File: literate.info, Node: capital_N_option, Next: o_option, Prev: n_option, Up: Programs-and-options
+
+ -N <info-filename> option
+
+(`lit2texi' only.) Arrange for the Info file to be called
+`<infofilename>'. By default, for input file `foo.xxx', the Info file
+will be called `foo.info'. For a multi-file document, the Info
+filename will be derived from the name of the first file encountered.
+
+
+File: literate.info, Node: o_option, Next: capital_O_option, Prev: capital_N_option, Up: Programs-and-options
+
+ -o <output-file> option
+
+Specify a specific output file. If not specified with `-o', then it's
+determined by puzzling over the input file's suffix (see the
+`-i <input-file>' option). When in doubt, it reverts to the standard
+output. You may also specify standard output as the "output file" with
+`-o -'.
+
+(For hackers only.) If the first character to the `-o' argument is a
+`|', then the output is piped through the shell command(s) that
+presumably follow.
+
+
+File: literate.info, Node: capital_O_option, Next: p_option, Prev: o_option, Up: Programs-and-options
+
+ -O option
+
+(`lit2texi' and `lit2latex' only.) At the beginning of each section,
+list the owner of the source file from which it was extracted.
+
+[APRIL91: There is some doubt just how this option would work; see
+section *Note recording-who-to-blame::.]
+
+
+File: literate.info, Node: p_option, Next: q_option, Prev: capital_O_option, Up: Programs-and-options
+
+ -p <pagebreak-hints> option
+
+(`lit2latex' only.) The (language-specific) code for typesetting the
+code in the document is passed the <pagebreak-hints> to further control
+how it is determined where pagebreaks are allowed. This is because it
+is not always obvious where to do pagebreaks in long stretches of code.
+
+These hints, if any, will be mentioned in the documentation of
+language-specific processing (Section *Note Language_specific::).
+
+[NOT IMPLEMENTED FOR ANY LANGUAGE]
+
+
+File: literate.info, Node: q_option, Next: r_option, Prev: p_option, Up: Programs-and-options
+
+ -q option
+
+(`lit2pgm' only.) Take quick shortcut. This will work if you are only
+using ribbon `main' (i.e., the usual recommended practice).
+
+Should be much faster than the plain `lit2pgm'. The `-q' option will be
+the *default* in the Glorious new Haskell compiler.
+
+
+File: literate.info, Node: r_option, Next: s_option, Prev: q_option, Up: Programs-and-options
+
+ -r <ribbons-to-get> option
+
+(`lit2pgm' only.) Extract code-ribbons `<ribbons-to-get>'
+(comma-separated), instead of the default ribbon, `main'. An artifact
+of the implementation is that `-r ''' gets you `main'; use
+`-r junkName' to extract nothing.
+
+
+File: literate.info, Node: s_option, Next: capital_S_option, Prev: r_option, Up: Programs-and-options
+
+ -s <stop-list-file> option
+
+(`lit2texi' and `lit2latex' only.) The file <stop-list-file> provides
+extra information for the automatic code-indexing about words that
+should *not* be indexed. One hacker's dross is another's gold.
+
+[I'm not sure this is used for any language yet. ToDo: check]
+
+
+File: literate.info, Node: capital_S_option, Next: t_option, Prev: s_option, Up: Programs-and-options
+
+ -S option
+
+(Not `lit2pgm'.) Process the input as if it is a standalone document.
+It is so processed if a `\documentstyle' command is seen, `-S' option
+or not.
+
+APRIL91: in jeopardy of going away; see section *Note
+pseudo-C-preprocessor::.
+
+
+File: literate.info, Node: t_option, Next: v_option, Prev: capital_S_option, Up: Programs-and-options
+
+ -t <typesetting-hints> option
+
+The (language-specific) routines for typesetting (really: outputting)
+the code in the document is passed the <typesetting-hints> to further
+control how typesetting is done.
+
+These (comma-separated) hints, if any, will be mentioned in the
+documentation of language-specific processing (Section *Note
+Language_specific::). Available hints:
+`-t tgrind':
+ Typeset code blocks by passing them through the `tgrind' program.
+
+`-t ruled':
+ Put lines (rules) above and below blocks of code. (The default may
+ vary with other outputting options.)
+
+`-t unruled':
+ Do *not* put lines (rules) above and below blocks of code.
+
+`-t bird':
+ Format all code (but not pseudocode) with Bird-tracks in the first
+ column. By default, only code input with Bird-tracks is so
+ formatted.
+
+`-t nobird':
+ Format all code without Bird-tracks.
+
+
+File: literate.info, Node: v_option, Next: x_option, Prev: t_option, Up: Programs-and-options
+
+ -v option
+
+Be verbose. This is really a debugging thing, too.
+
+
+File: literate.info, Node: x_option, Prev: v_option, Up: Programs-and-options
+
+ -x <xref-hints> option
+
+The (language-specific) code for indexing and/or cross-referencing the
+code in the document is passed the <xref-hints> to further control how
+things are done.
+
+A general one you can use is `-x noindex', to turn off code indexing.
+
+These hints, if any, will be mentioned in the documentation of
+language-specific processing (Section *Note Language_specific::).
+
+An example might be using `-l cpp -x extra:make' on the configuration
+files for `jmake'. These files have both C pre-processor and `make'
+things worthy of indexing/cross-referencing, and these options would
+ensure that the code was put through the appropriate routines for both
+languages.
+
+
+File: literate.info, Node: Info_etc, Next: april91-proposals, Prev: Programs-and-options, Up: Top
+
+Using your processed literate documents
+=======================================
+
+This section not written yet.
+
+It's supposed to be about all the neat ways to use your LaTeX- and
+Info-ised programs/documents.
+
+
+File: literate.info, Node: april91-proposals, Next: sept92-thoughts, Prev: Info_etc, Up: Top
+
+APRIL91 PROPOSALS
+=================
+
+* Menu:
+
+* april91-new-ideas:: New ideas.
+* april91-old-ideas:: Old ideas that still haven't gone anywhere.
+
+
+File: literate.info, Node: april91-new-ideas, Next: april91-old-ideas, Prev: april91-proposals, Up: april91-proposals
+
+New ideas
+---------
+
+These ideas have piled up over the past six months. NONE OF THEM ARE
+IMPLEMENTED. And some are TINY little things (and some are BIG).
+
+JULY91: I have fleshed out the section *Note literate-para-mode:: and
+section *Note lit2lit:: comments, as these directions piqued the
+interest of some fellow GRASPers.
+
+* Menu:
+
+* delatexify-commands:: Make the commands look less like LaTeX.
+* multiple-indexes:: Multiple indexes.
+* better-Haskell-indexing:: Better Haskell indexing.
+* revised-sectioning:: Revisions to the sectioning commands.
+* BNF-grammars:: A "BNF grammar" environment.
+* pseudo-C-preprocessor:: Fake "C pre-processing".
+* invisible-code:: Invisible code.
+* text-in-code:: Plain text in your code.
+* diff-fonts-in-text:: Using many "fonts" in text.
+* code-in-text-formatting:: Formatting code-ish things in text.
+* interface-with-papers:: Interface with plain LaTeX papers.
+* literate-para-mode:: A literate Para mode.
+* lit2lit:: A `lit2lit' program (to help implement a Para system).
+* xtex-options:: Generating LaTeX documents especially for `xtex'.
+* free-text-index:: A free-text "index".
+* magic-Info-nodes:: Other "magic" Info nodes....
+* revised-pgm-options:: Revise the way options are fed to `lit2*' programs.
+* mixing-Bird-code-and-other:: Mixing code in "Bird tracks" with other code.
+* code-reading-and-printing:: Decouple code reading and printing styles.
+
+
+File: literate.info, Node: delatexify-commands, Next: multiple-indexes, Prev: april91-new-ideas, Up: april91-new-ideas
+
+Make the commands look less like LaTeX
+......................................
+
+The biggest practical problem that has arisen among the (few) users of
+the literate programming stuff is that they think they're writing LaTeX
+files and are surprised/disappointed when LaTeX fails to grok their
+files. We have been too successful in making the notation "LaTeX-like!"
+
+One way to make the notation less LaTeX-like while maintaining the
+notation's familiarity is to switch to mixed-case names, used in a
+consistent manner; for example:
+ CURRENTLY WOULD BECOME ...
+ \documentstyle \documentStyle
+ \printindex \printIndex
+ \begin{flushleft} \begin{flushLeft}
+Command/environment names that are one word (e.g., `\begin{enumerate}')
+would be unchanged.
+
+Alternatively, we could make the literate-system case-insensitive where
+command names are concerned and merely make it our *convention* to use
+mixed-case names.
+
+
+File: literate.info, Node: multiple-indexes, Next: better-Haskell-indexing, Prev: delatexify-commands, Up: april91-new-ideas
+
+Multiple indexes
+................
+
+Having one index for a pretty-big program is a dubious proposition; you
+get a *huge* index. I think you need multiple indexes -- in the case
+of a compiler, you might then have a separate index for: parser,
+typechecker, syntactic desugarer, optimiser, etc.
+
+Let's assume you index all the pieces of a compiler (as above) as
+self-contained units. PROBLEM: it is the uses of functions, etc., that
+*cross* such boundaries that you would MOST like to have your attention
+drawn to.
+
+That problem aside, I think this is the basic solution:
+\defineindex{<index-tag-string>}:
+ Says that <index-tag-string> is "legal" hereafter.
+ Requiring/encouraging these `\defineindex' will help to catch
+ typos.
+
+\index[<index-tag-string>]{<entry>}:
+ The `\index' command has an optional <index-tag-string> with which
+ this <entry> should be tagged. The default tag string is `main'
+ (unless reset with `\setindex...'; below).
+
+\printindex[<index-tag-strings>]:
+ Print an index here, made up from all the entries that have one of
+ the <index-tag-strings>. The default tag string is (same
+ caveats...) `main'.
+
+\setcurrentindex{<index-tag-string>}:
+ Set the default tag string for `\index' commands in text.
+
+I think you could use the mechanism above to come close to Texinfo's
+idea about multiple indexes.
+
+
+File: literate.info, Node: better-Haskell-indexing, Next: revised-sectioning, Prev: multiple-indexes, Up: april91-new-ideas
+
+Better Haskell indexing
+.......................
+
+(The idea probably carries over to other languages.) Stick the whole
+literate-program Haskell source into an "interesting-thing finder"
+(call it `htags' :-), getting back (source-location, index-entry)
+pairs. Then the only trick is to tack each index-entry onto the code
+block nearest to the reported source-location.
+
+
+File: literate.info, Node: revised-sectioning, Next: BNF-grammars, Prev: better-Haskell-indexing, Up: april91-new-ideas
+
+Revisions to the sectioning commands
+....................................
+
+The main thing that is a pain about the current sectioning (see section
+*Note Sectioning::) is making up unique node names all the time. I
+propose the following "system" for the optional arg to `\section<n>';
+shown by example:
+\section{<title>}:
+ (As currently.) A default node name, made from the section number.
+ No `\label' created.
+
+\section[]{<title>}:
+ No node name, no node, no `\label'. Not recommended :-)
+
+\section[<the-usual>]{<title>}:
+ (As currently.) Arguably, the stuff to let you specific
+ next/prev/up explicitly should be dropped (to partly de-Info-ise
+ the notation).
+
+\section["]{<title>}:
+ (The new one.) The node name should be the same as the <title>
+ ("ditto"). No `\label' would be generated. Some massaging would
+ be required to remove nodename-hostile characters from the title
+ (e.g., colons).
+
+
+File: literate.info, Node: BNF-grammars, Next: pseudo-C-preprocessor, Prev: revised-sectioning, Up: april91-new-ideas
+
+A "BNF grammar" environment
+...........................
+
+This would work like the `verbatim' program used with the Haskell
+report; you could say:
+ \begin{grammar}
+ exp -> aexp
+ | exp aexp
+ | exp_1 op exp_2
+ | @-@ aexp
+ | @\@ apat_1 ... apat_n [gd] @->@ exp
+ | @if@ exp_1 @then@ exp_2 @else@ exp_3
+ | exp @where@ @{@ decls @}@
+ | @case@ exp @of@ @{@ alts @}@
+ | exp @::@ [context @=>@] atype
+ \end{grammar}
+and respectable BNF-looking stuff would appear in your output. Index
+entries for the definitions of nonterminals would be generated;
+possibly a `[noindex]' option to suppress that.
+
+I'd also like to do something for inference rules, but I'm fairly
+baffled about what that might be. (They can be mightily complicated,
+and it's not clear that a plain-ASCII form is possible.)
+
+
+File: literate.info, Node: pseudo-C-preprocessor, Next: invisible-code, Prev: BNF-grammars, Up: april91-new-ideas
+
+Fake "C pre-processing"
+.......................
+
+Change things so that literate documents are first put through a "fake
+C pre-processor" (this section assumes you know what a C pre-processor
+does). Notes:
+ 1. The relevant commands would start with `##' (to avoid confusion w/
+ the real thing); hence, `##if', `##endif', `##define',
+ `##include', etc.
+
+ 2. (Very important.) This pseudo-C-preprocessor does NOTHING inside:
+ * Code environments (and the Bird-track equivalent).
+
+ * Verbatim environments.
+
+ * `\tr' and `\pl' commands (and any friends they may have).
+
+ * `rawlatex' environments (next section).
+
+ 3. All of the current dubious `only<this-or-that>' environments and so
+ on would go away; what you currently write as:
+ \begin{onlystandalone}
+ \documentstyle[11pt,literate]{article}
+ \begin{document}
+ \title{Glasgow Literate Programming\\ User's Guide}
+ \date{April 1991}
+ \maketitle
+ \begin{onlylatex}
+ \tableofcontents
+ \end{onlylatex}
+ \clearpage
+ \end{onlystandalone}
+ would be re-written as:
+ ##if defined(STANDALONE)
+ \documentstyle[11pt,literate]{article}
+ \begin{document}
+ \title{Glasgow Literate Programming\\ User's Guide}
+ \date{April 1991}
+ \maketitle
+ ##if defined(MK_LATEX)
+ \tableofcontents
+ ##endif /* MK_LATEX */
+ \clearpage
+ ##endif /* STANDALONE */
+
+ 4. `##include' would take the place of the current bogosity
+ `\inputnow'.
+
+ 5. `##define' would take over from the current emasculated `\define'
+ and would emphasise the point that this literate notation is a
+ fixed notation, lacking general macros.
+
+ 6. Running this or that program would pre-##define certain symbols
+ (e.g., MK_LATEX), but I don't know exactly which just yet.
+
+ 7. Using ##defines and ##ifdef'ing easily generalises the
+ "standalone/partofdoc" dichotomy (which badly needs generalising).
+
+
+File: literate.info, Node: invisible-code, Next: text-in-code, Prev: pseudo-C-preprocessor, Up: april91-new-ideas
+
+Invisible code
+..............
+
+I am wondering if we shouldn't have a code environment of the form:
+ \begin{invisiblecode}
+ main (int argc, char **argv)
+ {
+ printf("Hello, Seaworld!\n");
+ }
+ \end{invisiblecode}
+for code that *should* be extracted (`lit2pgm') but that *should not*
+be displayed in `lit2latex/lit2texi' documents. This would probably be
+used when you want to include most, but not all, of a program's code --
+in a paper for publication, for example.
+
+My only fear is that it is too easily subject to abuse.
+
+Perhaps the C-pre-processing stuff is a better idea... (section *Note
+pseudo-C-preprocessor::).
+
+
+File: literate.info, Node: text-in-code, Next: diff-fonts-in-text, Prev: invisible-code, Up: april91-new-ideas
+
+Plain text in your code
+.......................
+
+In Knuth's WEB, you can refer to code-things in the text parts of the
+document/program *and* to text-things in your code. (As I recall,
+putting `|' around text switches it to whatever-you're-not-doing-now
+(code or text)).
+
+We have the first (the `@...@' shorthand to refer to code things while
+in text), but not the second: what's in a code environment is code just
+like you would see in an illiterate program in the same language.
+
+I guess the right solution is to have specially-marked comments (again,
+language-dependent) that say, "Don't treat this as just a comment in
+this programming language, but extract it and mangle/massage it as if
+it were literate-document text."
+
+A pain to implement. Not worth it?
+
+
+File: literate.info, Node: diff-fonts-in-text, Next: code-in-text-formatting, Prev: text-in-code, Up: april91-new-ideas
+
+Using many "fonts" in text
+..........................
+
+I find the `\tr' ("typewriter font") and `\pl' ("plain font") commands
+quite useful. (Yes, I know they go against the intensional markup
+principle (section *Note ASCII-declarative-markup::), but they are *so*
+convenient...)
+
+I'm inclined to make up notations for italics, small caps, and bold
+(and their ASCII-only "equivalents") and then try to systematize their
+use. Hmmm....
+
+I've found the Texinfo attempt to have a command for every different
+kind of thing you might want to talk about in a document to be too much
+and also unsatisfying.
+
+
+File: literate.info, Node: code-in-text-formatting, Next: interface-with-papers, Prev: diff-fonts-in-text, Up: april91-new-ideas
+
+Formatting code-ish things in text
+..................................
+
+Right now, the `@...@' shortcut notation means: Format this and
+automagically index it as for the code parts of the document.
+
+Strictly speaking then, I think the `@...@' notation should only be
+used to refer to things that *actually exist* in the code parts of the
+document, and *not* for code snippets, fragments, and other things
+mentioned along the way.
+
+For this latter task, perhaps a `\code[<language>]{<text>}' command is
+in order. This says: format this <text> as for <language>, but don't
+index it or pretend that it actually has anything to do with the real
+code in the program.
+
+
+File: literate.info, Node: interface-with-papers, Next: literate-para-mode, Prev: code-in-text-formatting, Up: april91-new-ideas
+
+Interface with plain LaTeX papers
+.................................
+
+At least in our setting, it is likely we've written one or more papers
+about some interesting part of the literate program we're writing. The
+paper is likely to be:
+ * relatively polished (so you'd like to re-use that effort);
+
+ * either a decent introduction to some part of the program, or a
+ succinct synopsis of some part;
+
+ * in straight LaTeX, but using features quite beyond our literate
+ markup, and including figures, etc.;
+
+ * not to be changed in any way.
+
+At the least, I'd like to be able to include the paper in toto, and
+have pointers into it (refs to its labels).
+
+More/better ideas welcome.
+
+
+File: literate.info, Node: literate-para-mode, Next: lit2lit, Prev: interface-with-papers, Up: april91-new-ideas
+
+A literate Para mode
+....................
+
+[See also section *Note lit2lit::.]
+
+The sad fact is that, at the moment, these literate programs/documents
+are typed in as just plain files and manipulated as such. They are
+only processed into LaTeX/Info documents after the fact (and only
+occasionally).
+
+Para mode is a GNU emacs mode that (roughly...) lets you both edit
+Texinfo files *and* jump around in them like Info files, based on the
+node structure. Either edit-as-normal or navigate-as-Info.
+
+I think there are possibilities for doing the same thing with these
+literate documents/programs. Then you'd get the benefits of
+navigation, following indexery, etc., *as you create the files*.
+
+One major problem (?): the literate sectioning makes it quite easy to
+navigate *within* a file, but, for it to be worth it, you'd like the
+"literate Para mode" (in navigation mode) to be able to carry you to
+the right place when you, e.g., want to go "up" from the first
+`\section' in a file.
+
+Implementation: my first cut would be: run something over all the
+literate files in a program to collect "Para-useful" information; save
+this somewhere -- this is the moral equivalent of a TAGS file. Then the
+navigation commands, etc., would use the pseudo-TAGS info to do their
+thing. Because the info would get out of date as you hack on your
+program, you'd re-make the pseudo-TAGS stuff whenever you stepped out
+for coffee, lunch, or sleep.
+
+
+File: literate.info, Node: lit2lit, Next: xtex-options, Prev: literate-para-mode, Up: april91-new-ideas
+
+A `lit2lit' program (to help implement a Para system)
+.....................................................
+
+[This might be a better way to implement a literate Para ...] Have a
+program that takes a set of `.lit' files, munges them to do all the
+usual cross-referencing, etc., etc., and then writes out *versions of
+the original files* with all the linking info, etc., etc., inserted as
+*comments*. Call the program `lit2lit'...
+
+If you took the `lit2lit' output and re-ran it through one of the other
+programs, e.g., `lit2latex', it would produce *exactly* the same output.
+
+The purpose of the information stored in comments would be to provide an
+Emacs mode (or something) enough information to help you jump around in
+a large program or generally do useful stuff.
+
+For example, it might insert links and things for something like Bob
+Weiner's Hyperbole system.
+
+I'm thinking that `lit2lit' would be re-run over a system's sources
+every night by `cron(1)'.
+
+
+File: literate.info, Node: xtex-options, Next: free-text-index, Prev: lit2lit, Up: april91-new-ideas
+
+Generating LaTeX documents especially for `xtex'
+................................................
+
+`Xtex' is a (free) DVI previewer with some hypertext-ish features; in
+particular, if you click on a reference to a label, then it takes you
+to the page where that label is defined. By generating a "LaTeX"
+document with all the linking info explicit (in the form of labels and
+references to them), `xtex' would do almost all the jumping-around
+stuff that `info' and `xinfo' do for you. *And you don't lose the font
+information.*
+
+
+File: literate.info, Node: free-text-index, Next: magic-Info-nodes, Prev: xtex-options, Up: april91-new-ideas
+
+A free-text "index"
+...................
+
+OK, even with all the automagical indexing, cross-referencing, etc.,
+occasions will arise when you say, "Help! I need to look absolutely
+everywhere for <foo>!" (Like you do with grep/tags, but preferably
+nicer -- all the tricks of the free-text indexing trade.)
+
+It would be great to have a "free text index" button or pseudo-node (an
+Info "node" that, when you jump to it, puts you in a free-text-search
+mode. Of course, the free-text-search should be able to plunk you down
+in the Info node you finally select).
+
+I really don't want to implement this myself :-)
+
+
+File: literate.info, Node: magic-Info-nodes, Next: revised-pgm-options, Prev: free-text-index, Up: april91-new-ideas
+
+Other "magic" Info nodes...
+...........................
+
+The "free text index" magic Info node makes me wish for *other*
+nodes-that-do-weird-things when you jump to them... You jump to it
+and... it starts up a PostScript previewer and shows me a picture... or
+sound... or my text editor so I can send a gripe to the maintainer of
+foo... and so on.
+
+
+File: literate.info, Node: revised-pgm-options, Next: mixing-Bird-code-and-other, Prev: magic-Info-nodes, Up: april91-new-ideas
+
+Revise the way options are fed to `lit2*' programs
+..................................................
+
+Using getopt(3)-style one-letter options is getting messy -- there are
+too many of them. Perhaps time for something more complicated...
+
+
+File: literate.info, Node: mixing-Bird-code-and-other, Next: code-reading-and-printing, Prev: revised-pgm-options, Up: april91-new-ideas
+
+Mixing code in "Bird tracks" with other code
+............................................
+
+When you put something in a code environment, e.g.,
+ \begin{code}
+ main _ = [ AppendChan stdout "Hi, Mom!\n" ]
+ \end{code}
+there is no doubt about what should be considered the "first column".
+On the other hand, if you see a "Bird track" equivalent:
+ > main _ = [ AppendChan stdout "Hi, Mom!\n" ]
+obviously the initial `>' should be stripped, but what about the space
+following? This matters if the code is to be put through, e.g., a C
+pre-processor, which looks for #'s in column 1.
+
+The solution I lean to is to have an option that says how much
+whitespace should be stripped off the front of Bird-track style code
+lines.
+
+
+File: literate.info, Node: code-reading-and-printing, Prev: mixing-Bird-code-and-other, Up: april91-new-ideas
+
+Decouple code reading and printing styles
+.........................................
+
+Code may come in either in code environments or in Bird-tracks. At
+present, it is printed in the same style as it came. This should
+remain the default.
+
+However, it would be nice to be able to say (with options), "OK, print
+*all* the code as if it were in Bird-track form" (or vice versa). This
+allows uniform presentation, while preserving programmers' preference
+for typing in one style rather than the other.
+
+
+File: literate.info, Node: april91-old-ideas, Prev: april91-new-ideas, Up: april91-proposals
+
+Old ideas that still haven't gone anywhere
+------------------------------------------
+
+These are ideas that have been around for a long time, HAVE NOT BEEN
+IMPLEMENTED, and no-one seems to have minded much.
+
+* Menu:
+
+* recording-who-to-blame:: \owner{<name>}.
+* test-burying:: Burying test cases in your document.
+* recording-changes:: Recording changes to your documents.
+
+
+File: literate.info, Node: recording-who-to-blame, Next: test-burying, Prev: april91-old-ideas, Up: april91-old-ideas
+
+\owner{<name>}
+..............
+
+(Not `lit2pgm'.) Give the "name" that should be listed as the "owner"
+of a section. If no `\owner' command has been seen, then the owner of
+the source file in which the first piece of text in the section was
+found is used.
+
+[I haven't really decided how this should work.]
+
+
+File: literate.info, Node: test-burying, Next: recording-changes, Prev: recording-who-to-blame, Up: april91-old-ideas
+
+Burying test cases in your document
+...................................
+
+The idea is that you can say:
+ \begin{test}{foo}
+ <Weird stuff in here>
+ \end{test}
+For this test `foo', the `<weird stuff in here>' would somehow say how
+to run the test, what should be fed to standard input (etc.), and what
+results to expect on standard output, standard error, and perhaps
+certain output files.
+
+The idea is to put the (simple?) test cases right next to the code that
+will be exercised.
+
+The problem is: tests can do pretty arbitrary things, and I don't see
+any neat way to encode that fact. Simply bunging full-blown shell
+scripts into the middle of your literate program hardly seems the
+solution. Hmmm.....
+
+If we had them: test environments don't nest.
+
+See ????? (ToDo) for a note on using hidden comments to highlight test
+information.
+
+
+File: literate.info, Node: recording-changes, Prev: test-burying, Up: april91-old-ideas
+
+Recording changes to your documents
+...................................
+
+Vaguely like the test case stuff, you might say:
+ \begin{change}
+ <who> & <when> & <tag> & <description of first change> \\
+ <who> & <when> & <tag> & <description of second change> \\
+ ... and so on ...
+ \end{change}
+This is intended to be like the ChangeLog stuff supported in Emacs
+(`C-x 4 a'). It really only makes sense to use it after software is no
+longer undergoing cataclysmic change (after it is released perhaps?).
+
+Anyway, the idea is to record your change notes right next to where you
+make them. [The program(s) to extract these notes and to collate them
+in the manner of your choice are not written yet.]
+
+These change environments don't nest.
+
+
+File: literate.info, Node: sept92-thoughts, Next: lit-install, Prev: april91-proposals, Up: Top
+
+SEPT92 THOUGHTS
+===============
+
+These are further ruminations, having had another year to watch how
+people do and do not use this system.
+
+Death to `ribbons' and code re-ordering:
+ No-one uses it, and it's pretty clunky in this system, both
+ conceptually and implementationally.
+
+Suppressable `detail':
+ Be able to mark sections as `detail', as well as to be able to put
+ `\begin{detail}/\end{detail}' around arbitrary stuff. Obviously,
+ you then want to format with/without the details in.
+
+A minimally-extensible notation?
+ Texinfo now supports setting and testing of variables, and the
+ using the values thereof.
+
+Support "all non-code is raw XXX":
+ Something like: given a flag `-r latex', then all non-code would be
+ taken to be pure LaTeX and wouldn't be mangled *at all*.
+
+ Another likely possibility: a `-r verbatim', to support the dubious
+ `verbatim' script that's popular in some circles.
+
+Stop automagic indexing of code-in-text:
+ I'm not sure it's useful.
+
+Throw out tree-grabbing (`-g <node>' option):
+ Too hacky, not used, probably inadequate.
+
+
+File: literate.info, Node: lit-install, Next: Index, Prev: sept92-thoughts, Up: Top
+
+Standalone installation of Glasgow literate programming
+=======================================================
+
+NOT DONE PROPERLY YET.
+
+Here are some short notes; they should work on a Sun4:
+ 1. If you don't have `perl', go get it.
+
+ 2. If you don't have `makeindex' (normally with the TeX distribution)
+ and/or `tgrind', go get them, if you wish. You can easily get by
+ without them, especially `tgrind'.
+
+ 3. Customise for your local configuration, by creating a suitable
+ `mkworld/site.jm' file. We supply a `site.dist' file that you can
+ copy and work from.
+
+ Setting `PerlCmd' correctly is *vital*.
+
+ All the Haskell-compiler stuff isn't important for the
+ literate-programming system.
+
+ Setting `TgrindHelperCmd' is important if you're going to try the
+ tgrind-ing stuff.
+
+ Setting the things for installation (near the end) is *vital*. You
+ will almost certainly need to set `InstRootDir', and perhaps some
+ others. If you don't set anything, the literate-programming
+ system will be installed (on a Sun4) in...
+
+ /usr/local/bin/sun4 things for the user to invoke (lit2mumble)
+ /usr/local/lib/literate/sun4 machine-specific support stuff
+ /usr/local/lib/literate machine-independent support stuff
+
+ 4. OK, you should be ready to go! From the top of the distribution...
+ % cd lit2xxx-X.YY
+ % ./STARTUP-literate >& startup.log
+ Everything should proceed to an obviously-successful conclusion
+ (check the log to see...).
+
+ 5. Test the system enough to see that it's not totally broken. Invoke
+ `lit2pgm', `lit2latex', or `lit2texi' directly from the
+ `literate/' directory, on some small test file of your choice,
+ even something as simple as...:
+ \section[test]{Test section}
+ This is a small test.
+ Then try, perhaps:
+ % literate/lit2latex -v -c test.lit
+
+ 6. If things seem basically happy, you can safely install the system.
+ % cd literate
+ % make -n install # trial run, just to see if it looks "right"
+ % make install # for real!
+
+ 7. To make the documentation (some pre-built stuff is in the distrib):
+ % cd literate
+ % make literate.dvi # or ...
+ % make literate.info # or ...
+ % make docs # to do both
+
+ In the unlikely event you wanted to install it, continue with:
+ % make install-docs
+
+ 8. You can now either delete the source or just clean up:
+ % make clean
+
+ 9. Save a copy of your configuration file `mkworld/site.jm' for next
+ time.
+
+If you have problems, please report them to me,
+partain@dcs.glasgow.ac.uk.
+
+
+File: literate.info, Node: Index, Prev: lit-install, Up: Top
+
+Index
+=====
+
+* Menu:
+
+* -D option: capital_D_option.
+* -A <pgm-name> option: A_option.
+* \appendix: \appendix.
+* \author: \author.
+* -c option: c_option.
+* \caption: \caption.
+* center environment: center_environment.
+* \centerline: \centerline.
+* \cleardoublepage: \clearpage-etc.
+* \clearpage: \clearpage-etc.
+* code (vs text): code-verissimilitude.
+* code (vs text)_2: notation-tut.
+* code environment: code_environment.
+* code index entries, extra: magic-things-in-code.
+* code ribbons: ribbons-details.
+* command: Command_reference.
+* comment environment: comment_environment.
+* comments, hidden: magic-things-in-code.
+* -d option: d_option.
+* \date: \date.
+* \define: \define.
+* description environment: description_environment.
+* display environment: display_environment.
+* \documentstyle: \documentstyle.
+* \em: \em.
+* enumerate environment: enumerate_environment.
+* environment: Command_reference.
+* -f <nodename-suffix> option: f_option.
+* figure environment: figure_environment.
+* flushdisplay environment: flushdisplay_environment.
+* flushverbatim environment: flushverbatim_environment.
+* \footnote: \footnote.
+* -g <node-name> option: g_option.
+* -H <dir1>:<dir2> option: H_option.
+* \heading: \heading.
+* hidden comments: magic-things-in-code.
+* -I <directories> option: capital_I_option.
+* -i <input-file> option: i_option.
+* index entries, extra ones in code: magic-things-in-code.
+* \index: \index.
+* \input: \input.
+* \inputnow: \inputnow.
+* \insertribbon: \insertribbon.
+* itemize environment: itemize_environment.
+* -L option: capital_L_option.
+* -l <language> option: l_option.
+* \label: \label.
+* LaTeX-like markup language: notation-tut.
+* \listoffigures: \listoffigures-etc.
+* \listoftables: \listoffigures-etc.
+* lit2text: Programs-and-options.
+* makeindex: Indexing.
+* \makeindex: Indexing.
+* \makeindex_2: \makeindex.
+* \maketitle: \maketitle.
+* menu environment: menu_environment.
+* \menuentry: \menuentry.
+* mkdependlit: Programs-and-options.
+* -N <info-filename> option: capital_N_option.
+* -n option: n_option.
+* node specification: Node_specifications.
+* \node: \node.
+* \noindex: Indexing.
+* -O option: capital_O_option.
+* -o <output-file> option: o_option.
+* onlyinfo environment: onlyinfo_environment.
+* onlylatex environment: onlylatex_environment.
+* onlypartofdoc environment: onlypartofdoc_environment.
+* onlystandalone environment: onlystandalone_environment.
+* \owner: recording-who-to-blame.
+* -p <pagebreak-hints> option: p_option.
+* \pageref: \pageref.
+* \pl: \pl.
+* \pounds: \pounds.
+* \printindex: Indexing.
+* \printindex_2: \printindex.
+* pseudocode environment: pseudocode_environment.
+* -q option: q_option.
+* quotation environment: quotation_environment.
+* -r <ribbons-to-get> option: r_option.
+* rawlatex environment: rawlatex_environment.
+* \ref: \ref.
+* ribbons, code: ribbons-details.
+* \rootsectiontype: How_to_section.
+* \rootsectiontype_2: \rootsectiontype.
+* -S option: capital_S_option.
+* -s <stop-list-file> option: s_option.
+* sectioning: Sectioning.
+* \Sectionref: sectiontype-and-ref.
+* \sectionref: \sectionref.
+* \sectionref_2: sectiontype-and-ref.
+* \sectiontype: \sectiontype.
+* \sectiontype_2: sectiontype-and-ref.
+* \standaloneornot: \standaloneornot.
+* \suppresscomments: \suppresscomments.
+* -t <typesetting-hints> option: t_option.
+* table environment: table_environment.
+* \tableofcontents: \tableofcontents.
+* tabular environment: tabular_environment.
+* text (vs code): code-verissimilitude.
+* text (vs code)_2: notation-tut.
+* \title: \title.
+* \tr: \tr.
+* -v option: v_option.
+* verbatim environment: verbatim_environment.
+* -x <xref-hints> option: x_option.
+
+
+
+Tag Table:
+Node: Top96
+Node: Highlights3235
+Node: Glasgow-objectives4426
+Node: on-line-form5734
+Node: medium-scale7013
+Node: language-independence7502
+Node: code-verissimilitude8172
+Node: ASCII-declarative-markup9013
+Node: hierarchical-structure10364
+Node: separate-compilation10933
+Node: one-file-many-purposes12171
+Node: Glasgow-NON-objectives13594
+Node: not-reinvent-LaTeX13939
+Node: reordering-unemphasis14489
+Node: Other-Glasgow-features15348
+Node: sectioning-large-documents15959
+Node: automatic-indexing17191
+Node: manual-indexing17991
+Node: automatic-cross-referencing18401
+Node: shortcut-notations19278
+Node: TeX-to-ASCII20306
+Node: Glasgow-NON-features20788
+Node: texinfo-limits21148
+Node: clumsy-node-namespace21925
+Node: clunky-implementation22467
+Node: notation-tut23069
+Node: micro-latex27347
+Node: Sectioning28813
+Node: section<n>29328
+Node: How_to_section31469
+Node: sectiontype-and-ref33368
+Node: Node_specifications34176
+Node: code-in-doc36990
+Node: usual-code-in-doc37673
+Node: ribbons-details38777
+Node: reordering-with-insertribbon40734
+Node: pseudocode41737
+Node: magic-things-in-code42151
+Node: Cross_references43836
+Node: Indexing44658
+Node: Examples47802
+Node: Simple_example48246
+Node: Typical_example48383
+Node: Hairy_example48527
+Node: Shortcuts48644
+Node: code-in-text49033
+Node: fonts-in-text50082
+Node: Command_reference50530
+Node: \appendix55179
+Node: \author55413
+Node: center_environment55571
+Node: \centerline55858
+Node: \caption56006
+Node: \clearpage-etc56229
+Node: code_environment56414
+Node: comment_environment56702
+Node: \date57125
+Node: \define57310
+Node: description_environment57944
+Node: display_environment58107
+Node: \documentstyle58478
+Node: \em59121
+Node: enumerate_environment59372
+Node: figure_environment59526
+Node: flushdisplay_environment59866
+Node: flushverbatim_environment60186
+Node: \footnote60569
+Node: \heading60958
+Node: \index61279
+Node: \input61677
+Node: \inputnow62348
+Node: \insertribbon62616
+Node: itemize_environment63072
+Node: \label63265
+Node: \listoffigures-etc63905
+Node: \makeindex64135
+Node: \maketitle64384
+Node: menu_environment64981
+Node: \menuentry65456
+Node: \node65681
+Node: \pounds66025
+Node: onlyinfo_environment66437
+Node: onlylatex_environment66736
+Node: onlypartofdoc_environment67047
+Node: onlystandalone_environment67517
+Node: \pageref68012
+Node: \pl68296
+Node: \printindex68822
+Node: pseudocode_environment69162
+Node: quotation_environment69495
+Node: rawlatex_environment69670
+Node: \ref70275
+Node: \rootsectiontype70433
+Node: \sectiontype70625
+Node: \sectionref70814
+Node: \standaloneornot71002
+Node: \suppresscomments71520
+Node: table_environment71882
+Node: \tableofcontents72131
+Node: tabular_environment72347
+Node: \title72654
+Node: \tr72805
+Node: verbatim_environment73347
+Node: Language_specific73903
+Node: Default_rules74638
+Node: Haskell_rules74918
+Node: Perl_rules75313
+Node: C_rules75698
+Node: Fortran_rules75904
+Node: Habits76190
+Node: Caveats77578
+Node: Programs-and-options79262
+Node: A_option82659
+Node: c_option82960
+Node: d_option83257
+Node: capital_D_option83472
+Node: f_option83810
+Node: g_option84290
+Node: H_option84930
+Node: i_option85315
+Node: capital_I_option85668
+Node: capital_L_option86231
+Node: l_option86947
+Node: n_option87442
+Node: capital_N_option87590
+Node: o_option87991
+Node: capital_O_option88570
+Node: p_option88934
+Node: q_option89524
+Node: r_option89894
+Node: s_option90246
+Node: capital_S_option90648
+Node: t_option90998
+Node: v_option91990
+Node: x_option92156
+Node: Info_etc92917
+Node: april91-proposals93232
+Node: april91-new-ideas93480
+Node: delatexify-commands95184
+Node: multiple-indexes96273
+Node: better-Haskell-indexing97769
+Node: revised-sectioning98270
+Node: BNF-grammars99339
+Node: pseudo-C-preprocessor100331
+Node: invisible-code102536
+Node: text-in-code103304
+Node: diff-fonts-in-text104187
+Node: code-in-text-formatting104915
+Node: interface-with-papers105714
+Node: literate-para-mode106544
+Node: lit2lit108098
+Node: xtex-options109171
+Node: free-text-index109809
+Node: magic-Info-nodes110535
+Node: revised-pgm-options111011
+Node: mixing-Bird-code-and-other111387
+Node: code-reading-and-printing112265
+Node: april91-old-ideas112882
+Node: recording-who-to-blame113373
+Node: test-burying113804
+Node: recording-changes114778
+Node: sept92-thoughts115626
+Node: lit-install116843
+Node: Index119654
+
+End Tag Table
diff --git a/web/glasgow/lit2x-0.16/literate/doc/literate.lit b/web/glasgow/lit2x-0.16/literate/doc/literate.lit
new file mode 100644
index 0000000000..d0a98f6410
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/literate.lit
@@ -0,0 +1,104 @@
+\begin{onlystandalone}
+\documentstyle[11pt,literate]{article}
+\begin{document}
+\title{Glasgow Literate Programming\\ User's Guide}
+
+\author{
+The GRASP Team \\
+Contact: Will Partain (partain\@dcs.glasgow.ac.uk)
+}
+\date{September 1992}
+\maketitle
+\begin{onlylatex}
+\tableofcontents
+\end{onlylatex}
+\clearpage
+\end{onlystandalone}
+
+This
+\standaloneornot{guide}{\sectiontype{Literate_guide}}
+introduces a suite of programs for literate programming.
+They support documentation as a natural part of programming;
+a program's organization focusses on understanding by humans.
+
+If you installing this system as a standalone entity, please
+see~\sectionref{lit-install}, near the end.
+
+This document begins with a few words about literate programming, the
+objectives of this system, and the Neat Stuff that this system is
+supposed to do for you (i.e., cheap, tasteless self-promotion).
+See~\sectionref{Highlights}.
+
+The real goods come next, most notably:
+\begin{itemize}
+\item
+an alleged ``tutorial'' on the \LaTeX{}-like markup language in which
+documents/programs are written (\sectionref{notation-tut});
+\item
+a ``reference manual'' about the same markup language; this tends to
+be what you consult once you are using the system
+(\sectionref{Command_reference});
+\item
+the programs/tools to mangle your documents/programs into useful forms
+(\sectionref{Programs-and-options}).
+\end{itemize}
+There are other sections, too, in greater-or-less states of
+usefulness.
+
+It would be a good idea to understand the rudiments of GNU Info files
+before reading much further---type \tr{info info} at your favourite
+Unix prompt. Or you could just ignore all mention of Info files...
+
+YOUR SUGGESTIONS FOR IMPROVING THIS SYSTEM ARE MOST WELCOME.
+
+DISCLAIMER: ``Literate programming'' is not my(WDP)/our area of
+expertise. This system has been developed mainly to suit our needs
+and has evolved on a grease-the-squeaky-wheel principle. However, we
+wouldn't bother to document it if we didn't think there was something
+to it!
+
+APRIL91 PROPOSALS: I am thinking about some changes to the system, NOT
+YET IMPLEMENTED. Discussion about most (all?) of them is gathered
+together in \sectionref{april91-proposals}. (You can find all
+discussion of proposed changes by grepping for ``APRIL91''.)
+
+SEPT92 THOUGHTS: Still haven't really worked on this system. I have
+typed a few further thoughts at the obvious place. I have fixed one
+or two bugs, and I have incorporated Adriaan Joubert's
+(adriaan\@dcs.qmw.ac.uk) stuff for ``literate Fortran,'' for which I
+am most grateful. (See, it really is easy to extend :-)
+
+For more information about ``real'' literate programming, the
+bibliography of literate programming in the (approx: ToDo) March~1991
+SIGPLAN Notices may be of use.
+
+% section on who should and shouldn't use this system?
+% (now in highlights)
+\input{highlights.lit}
+
+\input{lang_tut.lit}
+
+\input{lang_ref.lit}
+
+\input{lang_specific.lit}
+
+\input{habits.lit}
+
+\input{caveats.lit}
+
+\input{programs.lit}
+
+\input{using.lit}
+
+\input{april91.lit}
+
+\input{sept92.lit}
+
+\input{install.lit}
+
+%\input{lit_mode.lit}
+
+\begin{onlystandalone}
+\printindex
+\end{document}
+\end{onlystandalone}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/programs.lit b/web/glasgow/lit2x-0.16/literate/doc/programs.lit
new file mode 100644
index 0000000000..10ffb283b5
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/programs.lit
@@ -0,0 +1,300 @@
+\section[Programs-and-options]{Programs to process literate documents}
+
+In this incarnation, the programs \tr{lit2pgm}, \tr{lit2latex}, and
+\tr{lit2texi} (to extract program, \LaTeX{}, or GNU Texinfo fodder)
+are just three ways of invoking one killer \tr{perl} script,
+\tr{lit2stuff}.
+%\begin{comment}
+%A shell script \tr{lit2info}, to run
+%\tr{lit2texi} and then \tr{makeinfo} is not yet implemented. A script
+%\tr{lit2dvi} to run \tr{lit2latex} and then some sequence of
+%\tr{latex} and \tr{makeindex} invocations is also not out of the
+%question.
+%\end{comment}
+
+[Actually, this same script may be invoked as
+\tr{mkdependlit},\index{mkdependlit} to
+build a set of \tr{make} dependencies for a literate document, as
+\tr{lit2text}\index{lit2text}, to extract just the non-code text
+(perhaps for spell-checking), or as \tr{lit2changelog}, which is the
+(mainly unimplemented) interface to the changelog-slurping code. I
+ignore these details herein.]
+
+APRIL91: there are starting to be enough options that getopt-style
+one-letter names aren't enough/too obtuse. Some revision may be in
+order there... See \sectionref{revised-pgm-options}.
+
+For all three programs, their invocation takes the form
+\tr{lit2<whatever> [options] [input-file]}.
+Usually, output is to a file determined from the input-file's suffix
+(e.g., a \tr{.hs} file from a \tr{.lhs} file); if no input file is
+provided or life becomes confused, output is to the standard output.
+You can control input and output explicitly with the \tr{-i} and
+\tr{-o} options.
+
+Known file suffixes and what they mean:
+
+\begin{tabular}{ll}
+.lit & a literate-document file with no code in it (e.g., this one) \\
+.lhs & literate \Haskell{} source \\
+.lprl & literate Perl source \\
+.llex & literate Lex source \\
+.lc & literate C source \\
+.lh & literate C header source \\
+.ltex & literate \TeX{} macros \\
+.lf & literate FORTRAN \\
+\end{tabular}
+
+The suffixes \tr{.itex} and \tr{.itxi} indicate the intermediate files
+from ``separate compilation'' (to \LaTeX{} and Texinfo, respectively)
+of parts of a larger document.
+
+In ordinary life, given a literate C program \tr{foo} in file
+\tr{foo.lc}, one would hope that the following simple invocations
+would suffice:
+\begin{verbatim}
+lit2pgm foo.lc
+gcc -o foo foo.c
+
+lit2latex foo.lc
+latex foo.tex
+
+lit2texi foo.lc
+makeinfo foo.texi
+# (and if you really want to make things right, use the script...
+postmakeinfo foo.info
+# as well)
+\end{verbatim}
+
+What follows are the options to control these programs (and to
+complicate your life [and mine, too]). Not all command-line options
+make sense for all three programs; they are so noted. Options may be
+glopped together in the best getopt(3) style.
+
+\subsection*[A_option]{\pl{-A <pgm-name>} option}
+\index{a option@-A <pgm-name> option}
+(For hackers only.) Assume the program was invoked as \tr{<pgm-name>}.
+must be the first option given. Still has to be either \tr{lit2pgm},
+\tr{lit2texi}, or \tr{lit2latex}.
+
+\subsection*[c_option]{\pl{-c} option}
+\index{c option@-c option}
+(Not \tr{lit2pgm}.) Produce Texinfo or \LaTeX{} output (as
+appropriate) but don't try to ``link'' together with other parts of
+the same document. Think of the \tr{-c} option to a C compiler...
+
+\subsection*[d_option]{\pl{-d} option}
+\index{d option@-d option}
+Print debugging information. I will be monumentally surprised if this
+is of any use to you!
+
+\subsection*[capital_D_option]{\pl{-D} option}
+\index{D option@-D option}
+(\tr{lit2latex} only.) Print cross-references to code
+definitions in the text.
+
+APRIL91: this option stands some chance of being renamed if the
+pseudo-C-preprocessor comes in; see
+\sectionref{pseudo-C-preprocessor}.
+
+\subsection*[f_option]{\pl{-f <nodename-suffix>} option}
+\index{f option@-f <nodename-suffix> option}
+(\tr{lit2texi} only.) Append the string \tr{<nodename-suffix>} to
+every nodename in a file. This can be useful if you're trying to
+avoid nodename clashes between nodes in different parts of a big
+document (two of which might, for example, have nodes named
+``Introduction'').
+
+APRIL91: A feeble solution; see \sectionref{clumsy-node-namespace}.
+
+\subsection*[g_option]{\pl{-g <node-name>} option}
+\index{g option@-g <node-name> option}
+(\tr{lit2latex} only.) Grab the sub-tree of text for which node
+\tr{<node-name>} is the root. Used when you want to print a whole chapter
+or section or something, rather than just one Info node.
+
+{\em At this time, this option is only suitable for printing drafts.}
+
+What is actually done: the output \LaTeX{}-file consists of the
+pre-amble (really: everything before the first \tr{\section}
+command---not quite what you want), the subtree you asked for, and
+\tr{\end{document}}. Your section will be numbered \tr{1} no matter
+what.
+
+\subsection*[H_option]{\pl{-H <dir1>:<dir2>} option}
+\index{h option@-H <dir1>:<dir2> option}
+(For hackers only.) Used by villanous people to override the hardwired
+directories (\tr{<dir1>} for platform-specific files and \tr{<dir2>} for
+platform-independent \tr{perl} libraries) where the
+literate-programming system finds its stuff. Also see the \tr{-A}
+flag.
+
+\subsection*[i_option]{\pl{-i <input-file>} option}
+\index{i option@-i <input-file> option}
+Specify a specific input file. If not specified with \tr{-i}, then
+the first non-option command-line argument; if no such thing, then
+standard input. You may also specify standard input as the ``input
+file'' with \tr{-i -}.
+
+\subsection*[capital_I_option]{\pl{-I <directories>} option}
+\index{i option@-I <directories> option}
+Add (colon-separated) \tr{<directories>} to the front of the
+default path used to follow \tr{\input} commands (just \tr{.} at the
+moment). Only give one \tr{-I} option; I cannot promise what will
+happen if you give more than one.
+
+Slight magic: the \tr{.} in the path means: first, look in the
+directory where the file doing the \tr{\input}'ing is; if not there,
+look in the current working directory. (This is usually what you
+want.)
+
+\subsection*[capital_L_option]{\pl{-L} option}
+\index{l option@-L option}
+(\tr{lit2texi} only.) Alternate style of node linking---puts in more
+defaults for ``next'' and ``previous'' nodes. If a node doesn't have
+a ``next'' [``previous''] at its level (e.g., it's the last section in
+a chapter), then its ``next'' [``previous''] node will be the
+physically-next [-previous] one, regardless of sectioning level. (The
+default is for such nodes to have no next [previous] node.)
+
+[I like the -L node-linking scheme but \tr{makeinfo} issues warnings
+about it. APRIL91: newer version of some Info readers achieve the
+same effect using additional moving-around-the-tree commands.]
+
+\subsection*[l_option]{\pl{-l <language>} option}
+\index{l option@-l <language> option}
+(Not \tr{lit2pgm}.) Assume that any code in the input file is written in
+\pl{<language>} and process accordingly (automatic indexing, etc.).
+The \pl{<language>} is normally intuited from the input-file suffix
+(e.g., \tr{.lhs} suggests \Haskell{} code). The \tr{-x},
+\tr{-p}, and \tr{-t} options may be used to tweak cross-referencing,
+page-breaking, and typesetting of code, respectively.
+
+\subsection*[n_option]{\pl{-n} option}
+\index{n option@-n option}
+Follow \tr{\input} commands.
+
+\subsection*[capital_N_option]{\pl{-N <info-filename>} option}
+\index{n option@-N <info-filename> option}
+(\tr{lit2texi} only.) Arrange for the Info file to
+be called \tr{<infofilename>}. By default, for input file \tr{foo.xxx}, the
+Info file will be called \tr{foo.info}. For a multi-file
+document, the Info filename will be derived from the name of the
+first file encountered.
+
+\subsection*[o_option]{\pl{-o <output-file>} option}
+\index{o option@-o <output-file> option}
+Specify a specific output file. If not specified with \tr{-o}, then
+it's determined by puzzling over the input file's suffix (see the
+\tr{-i <input-file>} option). When in doubt, it reverts to the
+standard output. You may also specify standard output as the ``output
+file'' with \tr{-o -}.
+
+(For hackers only.) If the first character to the \tr{-o} argument is
+a \tr{|}, then the output is piped through the shell command(s) that
+presumably follow.
+
+\subsection*[capital_O_option]{\pl{-O} option}
+\index{o option@-O option}
+(\tr{lit2texi} and \tr{lit2latex} only.) At the beginning of each
+section, list the owner of the source file from which it was extracted.
+
+[APRIL91: There is some doubt just how this option would work; see
+\sectionref{recording-who-to-blame}.]
+
+\subsection*[p_option]{\pl{-p <pagebreak-hints>} option}
+\index{p option@-p <pagebreak-hints> option}
+(\tr{lit2latex} only.) The (language-specific) code for typesetting
+the code in the document is passed the \pl{<pagebreak-hints>} to
+further control how it is determined where pagebreaks are allowed.
+This is because it is not always obvious where to do pagebreaks in
+long stretches of code.
+
+These hints, if any, will be mentioned in the documentation of
+language-specific processing (\Sectionref{Language_specific}).
+
+[NOT IMPLEMENTED FOR ANY LANGUAGE]
+
+\subsection*[q_option]{\pl{-q} option}
+\index{q option@-q option}
+(\tr{lit2pgm} only.) Take quick shortcut. This will work if you are
+only using ribbon \tr{main} (i.e., the usual recommended practice).
+
+Should be much faster than the plain \tr{lit2pgm}.
+The \tr{-q} option will be the {\em default} in the Glorious new
+\Haskell{} compiler.
+
+\subsection*[r_option]{\pl{-r <ribbons-to-get>} option}
+\index{r option@-r <ribbons-to-get> option}
+(\tr{lit2pgm} only.) Extract code-ribbons \tr{<ribbons-to-get>}
+(comma-separated), instead of the default ribbon, \tr{main}.
+An artifact of the implementation is that \tr{-r ''} gets you
+\tr{main}; use \tr{-r junkName} to extract nothing.
+
+\subsection*[s_option]{\pl{-s <stop-list-file>} option}
+\index{s option@-s <stop-list-file> option}
+(\tr{lit2texi} and \tr{lit2latex} only.) The file
+\pl{<stop-list-file>} provides extra information for the automatic
+code-indexing about words that should {\em not} be indexed.
+One hacker's dross is another's gold.
+
+[I'm not sure this is used for any language yet. ToDo: check]
+
+\subsection*[capital_S_option]{\pl{-S} option}
+\index{s option@-S option}
+(Not \tr{lit2pgm}.) Process the input as if it is a standalone document.
+It is so processed if a \tr{\documentstyle} command is seen,
+\tr{-S} option or not.
+
+APRIL91: in jeopardy of going away; see
+\sectionref{pseudo-C-preprocessor}.
+
+\subsection*[t_option]{\pl{-t <typesetting-hints>} option}
+\index{t option@-t <typesetting-hints> option}
+The (language-specific) routines for
+typesetting (really: outputting) the code in the document is passed the
+\pl{<typesetting-hints>} to further control how typesetting is done.
+
+These (comma-separated) hints, if any, will be mentioned in the
+documentation of language-specific processing
+(\Sectionref{Language_specific}). Available hints:
+\begin{description}
+\item[\tr{-t tgrind}:]
+Typeset code blocks by passing them through the \tr{tgrind} program.
+%
+\item[\tr{-t ruled}:]
+Put lines (rules) above and below blocks of code.
+(The default may vary with other outputting options.)
+%
+\item[\tr{-t unruled}:]
+Do {\em not} put lines (rules) above and below blocks of code.
+%
+\item[\tr{-t bird}:]
+Format all code (but not pseudocode) with Bird-tracks in the first
+column. By default, only code input with Bird-tracks is so formatted.
+%
+\item[\tr{-t nobird}:]
+Format all code without Bird-tracks.
+\end{description}
+
+\subsection*[v_option]{\pl{-v} option}
+\index{v option@-v option}
+Be verbose. This is really a debugging thing, too.
+
+\subsection*[x_option]{\pl{-x <xref-hints>} option}
+\index{x option@-x <xref-hints> option}
+The (language-specific) code for indexing
+and/or cross-referencing the code in the document is passed the
+\pl{<xref-hints>} to further control how things are done.
+
+A general one you can use is \tr{-x noindex}, to turn off code
+indexing.
+
+These hints, if any, will be mentioned in the documentation of
+language-specific processing (\Sectionref{Language_specific}).
+
+An example might be using \tr{-l cpp -x extra:make} on the
+configuration files for \tr{jmake}. These files have both C
+pre-processor and \tr{make} things worthy of
+indexing/cross-referencing, and these options would ensure that the
+code was put through the appropriate routines for both languages.
diff --git a/web/glasgow/lit2x-0.16/literate/doc/sept92.lit b/web/glasgow/lit2x-0.16/literate/doc/sept92.lit
new file mode 100644
index 0000000000..dbbab52216
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/sept92.lit
@@ -0,0 +1,45 @@
+\section[sept92-thoughts]{SEPT92 THOUGHTS}
+
+These are further ruminations, having had another year to watch how
+people do and do not use this system.
+
+\begin{description}
+%------------------------------------------------------------------
+\item[Death to `ribbons' and code re-ordering:]
+
+No-one uses it, and it's pretty clunky in this system, both
+conceptually and implementationally.
+
+%------------------------------------------------------------------
+\item[Suppressable `detail':]
+
+Be able to mark sections as `detail', as well as to be able to put
+\tr{\begin{detail}/\end{detail}} around arbitrary stuff. Obviously,
+you then want to format with/without the details in.
+
+%------------------------------------------------------------------
+\item[A minimally-extensible notation?]
+
+Texinfo now supports setting and testing of variables, and the using
+the values thereof.
+
+%------------------------------------------------------------------
+\item[Support ``all non-code is raw XXX'':]
+
+Something like: given a flag \tr{-r latex}, then all non-code would be
+taken to be pure \LaTeX{} and wouldn't be mangled {\em at all}.
+
+Another likely possibility: a \tr{-r verbatim}, to support the dubious
+\tr{verbatim} script that's popular in some circles.
+
+%------------------------------------------------------------------
+\item[Stop automagic indexing of code-in-text:]
+
+I'm not sure it's useful.
+
+%------------------------------------------------------------------
+\item[Throw out tree-grabbing (\tr{-g <node>} option):]
+
+Too hacky, not used, probably inadequate.
+
+\end{description}
diff --git a/web/glasgow/lit2x-0.16/literate/doc/using.lit b/web/glasgow/lit2x-0.16/literate/doc/using.lit
new file mode 100644
index 0000000000..910091bb07
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/doc/using.lit
@@ -0,0 +1,6 @@
+\section[Info_etc]{Using your processed literate documents}
+
+This section not written yet.
+
+It's supposed to be about all the neat ways to use your \LaTeX{}- and
+Info-ised programs/documents.
diff --git a/web/glasgow/lit2x-0.16/literate/furuta_ref b/web/glasgow/lit2x-0.16/literate/furuta_ref
new file mode 100644
index 0000000000..fce03f7f3f
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/furuta_ref
@@ -0,0 +1,28 @@
+From carm@tove.cs.umd.edu Sat Aug 10 10:54:17 1991
+From: carm@tove.cs.umd.edu (Richard Chimera)
+Newsgroups: alt.hypertext,comp.editors,comp.text.sgml
+Subject: Re: Conversion of documents from paper to electronic (hypertext) format
+Date: 9 Aug 91 21:53:44 GMT
+Reply-To: carm@tove.cs.umd.edu (Richard Chimera)
+Followup-To: alt.hypertext
+Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742
+
+
+Check into:
+
+"A spectrum of automatic hypertext constructions," by Furuta, Plaisant, and
+Shneiderman. _Hypermedia_(1) 2, 1989, pp179-195.
+
+and
+
+"Automatically transforming regularly structured linearly documents into
+hypertext," by Furuta and Shneiderman. _Electronic Publishing - Origination,
+Dissemination, and Design_ 2, 4, 1990, pp211-229.
+
+
+--
+ Richard "carm" Chimera | Zorched by Zarches,
+ Human Computer Interaction Lab, U Md. | spaceman Spiff's
+ A.V. Williams Bldg, room 4166 | crippled craft crashes
+ College Park, MD 20742-3255 | on planet Plootarg!
+
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/ChangeLog b/web/glasgow/lit2x-0.16/literate/info-utils/ChangeLog
new file mode 100644
index 0000000000..cb5bc8c745
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/ChangeLog
@@ -0,0 +1,495 @@
+Sun Jun 7 10:24:37 1992 Brian Fox (bfox@cubit)
+
+ * info.c: New version 1.44.
+ * makeinfo.c: New version 1.47
+
+ * info.c:(main) If the user speficied the info file to use, and it
+ wasn't found, then exit immediately.
+
+ * makeinfo.texinfo: Updated documentation to include all of the
+ long options. Other minor cosmetic changes.
+
+Sat May 30 11:52:26 1992 Brian Fox (bfox@cubit)
+
+ * info.c (show_version_info) New function displays version
+ information. New long option "--version" causes this function to
+ be called, and then Info to exit.
+
+Wed May 27 09:52:22 1992 Brian Fox (bfox@cubit)
+
+ * info.c (dump_current_node) If the output filename is "-", then
+ dump to stdout.
+
+Sun May 24 11:30:20 1992 Brian Fox (bfox@cubit)
+
+ * makeinfo.c (begin_insertion, end_insertion) Do not close
+ paragraphs if producing a file with --no-headers.
+
+ * makeinfo.c (begin_insertion) Indentation of multiple paragraphs
+ appearing within an @enumerate is only done if the #define
+ INDENT_PARAGRAPHS_IN_TABLE is set (not the default). This makes
+ @enumerate paragraph indentation identical to @table and friends.
+
+Sat May 23 19:44:43 1992 Brian Fox (bfox@cubit)
+
+ * makeinfo.c: New version 1.46.
+
+ Changed `@set' to accept an equal sign followed by a value to
+ allow set variables to have values.
+
+ New command `@value{FOO}' inserts the value of the variable FOO.
+
+ @set accepts quoted values of the form: @set FOO="this is a list".
+ @ifclear and @ifset now count the conditionals encountered while
+ searching for their respective ends.
+
+ Command line arguments "-Dfoo" and "-Ubar" set and clear foo and
+ bar.
+
+Thu Apr 23 14:44:30 1992 Brian Fox (bfox@cubit)
+
+ * makeinfo.c: New version 1.45.
+
+ * makeinfo.c (cm_center): Add fudge_factor to centering
+ calculation to give more pleasing results. Call cm_noindent ()
+ before inserting any text.
+
+ * makeinfo.c (cm_exdent): Execute the line so that @var{} and
+ friends will work correctly.
+
+ * makeinfo.c (cm_node): When defaulting the next node, make sure
+ that the reference type is `menu'.
+
+Wed Apr 22 00:27:52 1992 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
+
+ * makeinfo.c: Indent #pragma.
+
+Wed Apr 8 23:11:51 1992 Charles Hannum (mycroft@hal.gnu.ai.mit.edu)
+
+ * makeinfo.c (usage): Terminate lines in string correctly.
+
+Mon Mar 9 23:38:57 1992 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu)
+
+ * info.c, makeinfo.c: Document long options as starting with `--',
+ not `+'.
+
+Sat Feb 22 02:15:00 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: (begin_insertion) @group does absolutely nothing
+ when found inside of an @example.
+
+ * texindex.c: New version 1.45 has cleanups, should compile under
+ VMS quietly.
+
+Thu Feb 20 16:21:54 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (cm_center) Inhibit output flushing to prevent the
+ executed line from disappearing before its length can be
+ calculated.
+
+ * makeinfo.c (inhibit_output_flushing, uninhibit_output_flushing)
+ Turn off and on actual disk writing.
+
+ * makeinfo.c: New version 1.44.
+
+Mon Feb 17 17:52:55 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (get_file_info_in_path, extract_colon_unit,
+ find_and_load_file) Two new functions, and modify
+ find_and_load_file () to use get_file_info_in_path (). You can
+ now supply multiple `-I<path>' flags to makeinfo in order to
+ specify directories which should be searched to find files
+ included with @include.
+
+Sat Feb 8 00:06:17 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (usage): Update the help message.
+
+ * Makefile.in: Hack kludge to get -traditional into the CFLAGS. I
+ hate auto-configure, and worse, where does it get off deciding for
+ me that I want to use a specific compiler simply because I have a
+ file called gcc in my PATH?
+
+ * makeinfo.c (new functions): New functions cm_macro, cm_unmacro,
+ add_macro, execute_macro, delete_macro () all implement new @macro
+ construct. This is conditionally compiled with #define HAVE_MACROS.
+
+Fri Feb 7 18:27:45 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (cm_center): Center the line *after* "executing" it.
+
+ * info.c: Remove "true", "false", and "boolean", replacing them
+ with 1, 0, and int.
+
+Tue Jan 21 01:18:25 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (cm_titlefont) New function does nothing special but
+ makes life easier.
+
+Fri Jan 10 16:43:04 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (cm_code) Increment/decrement in_fixed_width_font
+ while processing the text inside of an @code (includes @samp, @file).
+
+Wed Jan 8 02:52:33 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: (close_insertion_paragraph) New function gets called
+ to close certain types of insertions. This includes @format,
+ @example, etc. New variable line_already_broken describes the
+ state of the output file to close/start_paragraph ().
+
+Tue Jan 7 02:24:10 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: (cm_node) Get and remember sectioning commands even
+ for those nodes which are not currently defaulting. Such nodes
+ can contain menus whose nodes are defaulted, and we need to know
+ the sectioning level of the node containing the menu.
+
+ * makeinfo.c: Removed definitions for "true", "false", and the
+ typedef for "boolean". Changed all code accordingly. Added
+ defines for BRACE_ARGS and NO_BRACE_ARGS to increase readability
+ of the CommandTable.
+
+ * makeinfo.c (begin_insertion) Do not
+ inhibit_paragraph_indentation for @table and friends.
+
+Mon Jan 6 11:52:36 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (convert) WHoops! Remove surrounding whitespace from
+ OUTPUT_FILENAME before using.
+
+ * makeinfo.c: (end_insertion) If an @end INSERTION is followed by
+ a blank line, then start a new paragraph there, otherwise close
+ the current one without a blank line.
+
+ * makeinfo.c: (main, convert) Add code to support -o FILE (+output
+ FILE) option. The output filename generated from this option
+ overrides the filename appearing in the @setfilename command.
+
+Mon Dec 23 23:46:42 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
+
+ * texindex.c: Change POSIX ifdefs to HAVE_UNISTD_H and _POSIX_VERSION.
+
+Wed Dec 18 04:26:02 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (end_insertion) Close paragraphs removing last
+ inserted newline which comes from @end INSERTION.
+
+ * makeinfo.c (start_paragraph) Do not unconditionally set the
+ output column from the desired indentation; use an interim value
+ instead and keep in mind that some indentation may have already
+ been done.
+
+Fri Dec 6 01:25:09 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
+
+ * texindex.c: Conditionalize on _AIX (which is predefined) instead
+ of AIX, just like makeinfo does.
+
+Sat Nov 23 22:43:05 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: (cm_vtable) New command @vtable is just like
+ @ftable, but adds an entry to the variable index instead of the
+ function index.
+
+Thu Nov 21 00:12:51 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * info.c: #define S_ISREG macro if not defined, and use the
+ definition.
+
+Wed Nov 20 01:07:57 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: (flush_output) Turn off meta bit on sentence enders
+ that were ignored.
+
+Fri Nov 1 01:09:43 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
+
+ * Makefile.in: Add texindex.
+ * texindex.c: Add more #ifdefs, for VMS and USG.
+ (usage): New function.
+ (decode_command): Call it if given invalid option or no files.
+ Use getopt.
+
+Sat Sep 21 17:02:42 1991 Info Maintainer (info at gnuwest.fsf.org)
+
+ * makeinfo.c: New command @deftypemethod added.
+
+ * makeinfo.c: (cm_cartouche) New function which is ignored in
+ makeinfo.
+
+ * makeinfo.c: (cm_br) If we skip a newline then increment
+ line_number.
+
+ * makeinfo.c: (reader_loop) ignore the whitespace on lines which
+ appear blank.
+
+ * index_add_arg (), close_paragraph (); Call ignore_blank_line ()
+ to tell the reader that the previous line disappeared from the
+ input stream. New function ignore_blank_line ().
+
+Tue Sep 3 22:38:18 1991 Info Maintainer (info at gnuwest.fsf.org)
+
+ * makeinfo.c: (cm_footnotestyle, cm_paragraphindent) Fix bogus
+ call to get_rest_of_line ().
+
+Tue Jun 11 00:34:12 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * info.c: Fixed SIGWINCH display bugs. Windows can now be resized
+ at will.
+
+Mon Jun 10 11:25:01 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c New function cm_math () does nothing but accepts
+ arguments.
+
+ * makeinfo.c (flush_output) only change the 8th bit for space,
+ tab, or newline. This protects ISO character sets.
+
+ * info.c: opsys_filename (); Return only the names of regular
+ files, not directories or block special devices.
+
+ * makeinfo.c (add_char) Fixed bug in filling which could cause 78
+ character lines to be filled incorrectly when fill_column was 79.
+
+Tue Jun 4 13:34:57 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: Add @paragraphindent and @footnotesytle as
+ interactive commands to change default paragraph indentation and
+ footnote style.
+
+Thu Jan 31 10:55:34 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * @cite now produces `...' instead of ``...''.
+
+Tue Jan 29 16:47:01 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: add flushleft, and flushright.
+ (cm_xref): all calls to add_word_args () are now calls to
+ execute_string () so that @code{@@bullet} produces the correct
+ output. The call to normalize_node_name () from get_xref_token
+ () is removed, since xref now calls execute string.
+ (end_insertion) now sets last_char_was_newline so that no extra
+ indentation can appear on the following text line.
+
+Sun Jan 27 22:32:45 1991 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (args_from_string): Hack tokenization to consider a
+ command followed immediately by braces to be a single token
+ (including the braces and contents of same).
+
+Thu Jun 28 15:01:51 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c, info.c, Makefile: Change SYSV to USG.
+
+Wed Jun 27 12:22:12 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: new function cm_today () produces the date in the
+ output document.
+
+Wed May 30 13:00:09 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c (cm_xref) If arguments 4 or 5 are present, then we
+ use argument 2 as the node name, unless it is empty, in which case
+ we use argument one. See how easy this is to use?
+
+ * makeinfo.c (many index functions) Handle code indices by
+ inserting @code{} around the index entry item when it is being
+ printed. Keep track of which type of index was used to insert
+ this item into the index.
+
+ * makeinfo.c (reader_loop) Paired single quotes turn into double
+ quote (outside of fixed-width font insertions. Multiple dashes
+ don't shrink down to double dashes inside of fixed-width font
+ insertions.
+
+Sun May 27 11:23:27 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c Merge in VMS changes. Adds single change to
+ find_and_load (), and mimics some things that SYSV needs for
+ headers.
+
+Mon May 21 11:39:43 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c Added @smallbook.
+
+Thu Apr 26 05:01:04 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c: Output newline before tag table leader. @sp X
+ doesn't close paragraph anymore, it just acts as if you personally
+ typed in X newlines.
+
+Mon Apr 16 02:26:11 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * makeinfo.c Fixed splitting to output the final node in a
+ separate subfile if outputting it in the current subfile would
+ make the subfile too large.
+
+Sun Jan 14 10:34:42 1990 Brian Fox (bfox at sbphy.ucsb.edu)
+
+ * makeinfo.c: new function normalize_node_name () gets called from
+ get_node_token (), get_xref_token (), glean_node_from_menu (). It
+ allows (by hacking) @@ in the name of a node. This leaves @Top
+ undefined as to what action to take: that is to say that @@Top and
+ @Top are identical node names.
+
+ * makeinfo.c:begin_insertion (). Made @example and friends
+ sensitive to newlines so that pending_indent wouldn't build up.
+ This fixed bug of extra indentation if @example was followed
+ immediately by a blank line, instead of text.
+
+Mon Dec 11 11:47:28 1989 Brian Fox (bfox at rice-chex)
+
+ * Changed cons_string to savestring everywhere.
+
+ * Added info.tar.Z as a target to the Makefile.
+
+Mon Dec 11 00:28:14 1989 David J. MacKenzie (djm at rice-chex)
+
+ * Merge modification history comments from info.c and makeinfo.c
+ into the ChangeLog.
+
+ * makeinfo.c (main): Use getopt_long.
+ (usage): Describe new option syntax, adding descriptions
+ of the verbose and paragraph-indent options.
+
+ * Makefile: Add rules to link makeinfo with getopt.
+
+Sun Dec 10 01:26:34 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
+
+ * Makefile: Move default info directory path definition from info.c
+ and shorten it, since it will now be changed appropriately for
+ each site.
+ Rearrange rules to put those that are likely to be changed locally
+ at the beginning.
+ Define SHELL, don't define DOC (wasn't used).
+ (dist): New rule to make info.tar and info.tar.Z.
+
+ info.c (get_terminal_info): Use fgets instead of gets.
+ Flush output before reading.
+ (info_signal_handler): Don't declare extra unused args.
+ (help_possible_completions): Don't return a value; never used.
+ (help_use_info): Ditto.
+ (main): Add missing arg to call of get_node.
+ (toploop): Ditto.
+ (build_notes): Move misplaced ')'.
+ Global: Added some casts to function calls.
+ Commented out some unused code.
+
+Sat Dec 9 18:44:33 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
+
+ * info.c: Move some function decl's outside of function bodies.
+ Include getopt.h.
+ (main): Use getopt_long. Fix error in use of printf.
+ Add /usr/local/emacs/info to the default directory path so it
+ works at the AI lab.
+ (usage): Rename from explain. Update message.
+ (eat_argument): Function removed.
+
+ * Makefile: Add rules for linking info with getopt.
+ Rename DOT_OHS macro to OBJECTS.
+
+Tue Nov 7 17:48:31 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * makeinfo.c (CommandTable): Define `@ ' and `@RET'.
+
+Mon Nov 6 08:15:20 1989 Brian Fox (bfox at rice-chex)
+
+ * makeinfo.c: Added defaulting Next, Prev, and Up pointers in a
+ @node command without arguments. Revamped validation to be more
+ robust. Added new validation rules (see comment at validat_file).
+
+ * Changed Makefile to include ChangeLog and default-nodes.texinfo
+ in info.tar.Z.
+
+Sun Nov 5 02:27:35 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * makeinfo.c (convert): Split even if errors.
+
+Tue Aug 22 14:51:11 1989 Robert J. Chassell (bob at hobbes.ai.mit.edu)
+
+ * makeinfo.c (defun_internal): Line that begin with an asterisk
+ are mistook for menu entries by info; so, replaced `* ' prior to
+ function, variable, etc. definitions with ` * '.
+
+... Aug .. ........ 1989 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: Added the @def... commands.
+ Added the -pi flag for paragraph_start_indent.
+
+Wed Jul 6 ........ 1989 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * info.c: Indirect tags are not assumed to point close to the node.
+ Instead, they point to where the node would have been, had the the
+ file never been split. Thus, the header of a split file is
+ compensated for, by dynamically figuring out how long it is every
+ time we read in a file.
+
+Mon Jun 12 19:48:58 1989 Robert J. Chassell (bob at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: @result, @expansion, @print, @error, @point, @equiv added
+
+... Jun .. ........ 1989 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: Make sure that the NEXT node has a PREV that points
+ to it.
+
+ * makeinfo.c: Added @result, @expansion, @equiv, @print, @error
+ and @point.
+
+Tue May 2 23:41:37 1989 Randall Smith (randy at rice-chex.ai.mit.edu)
+
+ * makeinfo.c (find_index): Fixed comparison to be versus -1.
+
+Fri Apr 7 14:24:27 1989 Randall Smith (randy at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: Installed new version from bfox.
+ * makeinfo.c (get_until): Fixed typo; == should have been =.
+
+... Apr .. ........ 1989 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: Added validation of Up fields. They now have to
+ have a menu item which points to them in the indicated node.
+
+Thu Feb 25 10:22:00 1989 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * info.c: Made info_directory_paths try to get its value from the
+ environment variable INFO_DIRECTORY_PATHS. Added cons_string
+ in an attempt to get rid of the brain-damage (read brian-damage)
+ I originally wrote in here. Death to static limits!
+
+... Oct .. ........ 1988 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: Allowed user defined commands. In the specific,
+ allowed the the user to make his/her own indices. We define the
+ default ones.
+
+Fri Oct 9 13:03:00 1988 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * info.c: Virgin release 1.0.
+
+ * info.c: Made the completer not use static size variables.
+ Also made the completer more generic. Maybe this will be of
+ some use someday.
+ Changed file_error to incorporate code suggestions from
+ Roland McGrath.
+ Changed idiot error messages. We still need some canonical
+ location for the initial Info directory path.
+
+... Jul .. ........ 1988 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: added code to handle un-closed braces at the start
+ of a node, un-finished insertions at the start of a node,
+ and outputting the `header' at the start of each info split sub-file.
+
+ * makeinfo.c: Made split_file NOT update the tags table to reflect
+ the changes in the output files. This means the reader has also
+ changed.
+
+... Jun .. ........ 1988 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: fixed filling to do the right thing at sentence ends.
+ stopped automatically removing filename extensions on output
+ split files.
+
+... Apr .. ........ 1988 Brian Fox (bfox at rice-chex.ai.mit.edu)
+
+ * makeinfo.c: added splitting.
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/Jmakefile b/web/glasgow/lit2x-0.16/literate/info-utils/Jmakefile
new file mode 100644
index 0000000000..177c56bb49
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/Jmakefile
@@ -0,0 +1,52 @@
+/* makefile that comes with distribution is in Makefile.original */
+
+PROGRAMS = makeinfo info postmakeinfo
+/* the last is a script that helps cooperation w/ the literate programming stuff */
+
+all:: $(PROGRAMS)
+
+MsubNeededHere(postmakeinfo)
+
+/* CC = gcc termcap'ping does not work right with gcc on sun4s for info */
+
+# Colon-separated list of directories in which to look for info files.
+DEFAULT_INFOPATH = DefaultInfoPath
+
+# Command used to print out a text file. The filename follows this command.
+INFO_PRINT_COMMAND = lpr
+
+PATHSPEC = -DDEFAULT_INFOPATH='"$(DEFAULT_INFOPATH)"'
+PRINTSPEC = -DINFO_PRINT_COMMAND='"$(INFO_PRINT_COMMAND)"'
+INFO_DEFINES = $(PATHSPEC) $(PRINTSPEC)
+
+# TRACK_SRCFILE and ALLOW_JUNK are partain additions
+MAKEINFO_DEFINES = -DTRACK_SRCFILE -DALLOW_JUNK
+
+/* roll them together; hurts nothing... */
+CPP_DEFINES = $(INFO_DEFINES) $(MAKEINFO_DEFINES)
+
+SRCS_C = info.c makeinfo.c getopt.c getopt1.c
+INFO_OBJS_C = info.o getopt.o getopt1.o
+MAKEINFO_OBJS_C = makeinfo.o getopt.o getopt1.o
+
+/*
+HEADERS = getopt.h
+SUPPORT = Makefile ChangeLog testfile.texinfo test-suite.texinfo\
+ default-nodes.texinfo
+*/
+
+BuildPgm(info,$(CC),$(INFO_DEFINES) $(CFLAGS),$(INFO_OBJS_C),-ltermcap,)
+
+BuildPgm(makeinfo,$(CC),$(MAKEINFO_DEFINES) $(CFLAGS),$(MAKEINFO_OBJS_C),,)
+
+MsubProgramScriptTarget(PerlCmd,postmakeinfo,postmakeinfo.prl,,)
+
+InstallBinaryTarget(info, $(INSTBINDIR))
+InstallBinaryTarget(makeinfo, $(INSTBINDIR))
+InstallScriptTarget(postmakeinfo, $(INSTSCRIPTDIR))
+
+CDependTarget( $(SRCS_C) )
+
+EtagsNeededHere(tags) /* need this to do "make tags" */
+ClearTagsFile()
+CTagsTarget( *.h $(SRCS_C) )
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.in b/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.in
new file mode 100644
index 0000000000..ab49868d92
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.in
@@ -0,0 +1,124 @@
+# Makefile for the info sources... -*- text -*-
+# Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+# Things you might add to DEFS:
+# -DSTDC_HEADERS If you have ANSI C headers and libraries.
+# -DHAVE_UNISTD_H If you have unistd.h.
+# -DUSG If you have System V/ANSI C string and
+# memory functions and headers.
+# -DUSGr3 If you need to include sys/stream.h and sys/ptem.h
+# to get the screen size from the kernel.
+DEFS = @DEFS@
+
+CFLAGS = -g
+LDFLAGS = -g
+
+LIBS = @LIBS@
+
+# Colon-separated list of directories in which to look for info files.
+DEFAULT_INFOPATH = .:$(infodir):/usr/gnu/info:/usr/local/emacs/info:/usr/local/lib/emacs/info
+
+# Command used to print out a text file. The filename follows this command.
+INFO_PRINT_COMMAND = lpr
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+
+# Where installed binaries go.
+bindir = $(exec_prefix)/bin
+
+# Where info files go.
+infodir = $(prefix)/info
+
+# Where manual pages go, and their extension (not including `.').
+mandir = $(prefix)/man/man1
+manext = 1
+
+#### End of system configuration section. ####
+
+PATHSPEC = -DDEFAULT_INFOPATH='"$(DEFAULT_INFOPATH)"'
+PRINTSPEC = -DINFO_PRINT_COMMAND='"$(INFO_PRINT_COMMAND)"'
+INFO_FLAGS = $(PATHSPEC) $(PRINTSPEC)
+
+SOURCES = info.c makeinfo.c texindex.c getopt.c getopt1.c
+OBJECTS = info.o makeinfo.o texindex.o getopt.o getopt1.o
+HEADERS = getopt.h
+SUPPORT = Makefile.in configure
+
+THINGS_TO_TAR = $(SOURCES) $(HEADERS) $(SUPPORT)
+
+PROGS = info makeinfo texindex
+
+all: $(PROGS)
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(DEFS) $<
+
+info: info.o getopt.o getopt1.o
+ $(CC) $(LDFLAGS) -o $@ info.o getopt.o getopt1.o -ltermcap $(LIBS)
+
+info.o: info.c
+ $(CC) -c $(CFLAGS) $(INFO_FLAGS) $info.c<
+
+makeinfo: makeinfo.o getopt.o getopt1.o
+ $(CC) $(LDFLAGS) -o $@ makeinfo.o getopt.o getopt1.o $(LIBS)
+
+makeinfo.o: makeinfo.c
+ $(CC) -c $(CFLAGS) $(MAKEINFO_FLAGS) $makeinfo.c<
+
+texindex: texindex.o getopt.o getopt1.o
+ $(CC) $(LDFLAGS) -o $@ texindex.o getopt.o getopt1.o $(LIBS)
+
+info.o makeinfo.o texindex.o getopt1.o: getopt.h
+
+install: all
+ for f in $(PROGS); do $(INSTALL_PROGRAM) $$f $(bindir)/$$f; done
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+clean:
+ rm -f $(PROGS) $(OBJECTS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile config.status
+
+realclean: distclean
+ rm -f TAGS
+
+dist: $(THINGS_TO_TAR)
+ rm -rf info-dist
+ mkdir info-dist
+ (cd info-dist; for i in $(THINGS_TO_TAR); do ln -s ../$$i .; done)
+ tar chzf info.tar.Z info-dist
+ rm -rf info-dist
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.original b/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.original
new file mode 100644
index 0000000000..076350ba3b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/Makefile.original
@@ -0,0 +1,69 @@
+# Makefile for the info sources... -*- text -*-
+
+# Define OS = -DUSG if you are compiling for System V-like machines.
+# OS = -DUSG
+
+# Define OS = -DVMS if you are compiling under VMS.
+# OS = -DVMS
+
+CC = gcc
+DEBUG_FLAG = -g
+#PROFFLAGS = -pg
+CFLAGS = $(DEBUG_FLAG) $(PROFFLAGS) $(OS)
+LDFLAGS = $(PROFFLAGS) $(DEBUG_FLAG) #-Bstatic
+
+BINDIR = /usr/gnu/bin
+
+# Colon-separated list of directories in which to look for info files.
+DEFAULT_INFOPATH = .:/local/doc/info
+
+# Command used to print out a text file. The filename follows this command.
+INFO_PRINT_COMMAND = lpr
+
+PATHSPEC = -DDEFAULT_INFOPATH='"$(DEFAULT_INFOPATH)"'
+PRINTSPEC = -DINFO_PRINT_COMMAND='"$(INFO_PRINT_COMMAND)"'
+INFO_FLAGS = $(PATHSPEC) $(PRINTSPEC)
+
+SOURCES = info.c makeinfo.c getopt.c getopt1.c
+OBJECTS = info.o makeinfo.o getopt.o getopt1.o
+HEADERS = getopt.h
+SUPPORT = Makefile ChangeLog testfile.texinfo test-suite.texinfo\
+ default-nodes.texinfo makeinfo.texinfo info.1
+
+THINGS_TO_TAR = $(SOURCES) $(HEADERS) $(SUPPORT)
+
+PROGS = info makeinfo
+
+all: $(PROGS)
+
+info: info.o getopt.o getopt1.o
+ $(CC) $(LDFLAGS) -o info info.o getopt.o getopt1.o -ltermcap
+
+info.o: info.c
+ $(CC) -c $(CFLAGS) $(INFO_FLAGS) info.c
+
+makeinfo: makeinfo.o getopt.o getopt1.o
+ $(CC) $(LDFLAGS) -o makeinfo makeinfo.o getopt.o getopt1.o
+
+makeinfo.o: makeinfo.c
+ $(CC) -c $(CFLAGS) $(MAKEINFO_FLAGS) makeinfo.c
+
+install: info makeinfo
+ for i in $(PROGS); \
+ do install -c $$i $(BINDIR); \
+ done
+
+info.tar.Z: $(THINGS_TO_TAR)
+ tar -chof info.tar $(THINGS_TO_TAR)
+ compress < info.tar > info.tar.Z
+
+dist: $(SOURCES) $(HEADERS) $(SUPPORT)
+ mkdir info-dist
+ (cd info-dist; for i in $(SOURCES) $(HEADERS) $(SUPPORT); do \
+ ln -s ../$$i .; done)
+ tar chof info.tar info-dist
+ rm -r info-dist
+ compress < info.tar > info.tar.Z
+
+clean:
+ rm -f $(PROGS) $(OBJECTS)
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/README b/web/glasgow/lit2x-0.16/literate/info-utils/README
new file mode 100644
index 0000000000..87ebf8a46d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/README
@@ -0,0 +1,15 @@
+This is a hacked version of the std GNU `info' and `makeinfo'.
+The last version compared against was in the texinfo-2.15 package.
+
+The version of Dave Gillespie's info.el is 1.05; it's *great*!
+
+"makeinfo" is the only pgm which we've mangled significantly. The
+diffs vs the GNU-distributed `makeinfo' and our "enhancements", both
+turned on by #defines:
+
+* -DALLOW_JUNK puts the text of unrecognized commands through (vs
+ tossed away)
+
+* -DTRACK_SRCFILE puts in additional commands @srcfile and @srclineno,
+ which try to allow tracking of the original src file (assuming the
+ .texinfo file was generated from something else).
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/bug.texi b/web/glasgow/lit2x-0.16/literate/info-utils/bug.texi
new file mode 100644
index 0000000000..70fa644493
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/bug.texi
@@ -0,0 +1,12 @@
+@setfilename bug-info
+
+@node Top, , , (dir)
+
+@subsubsection Options for the driver @samp{ghc}
+
+@menu
+* Controlling_phases:: What phases in what order.
+* Verbosity:: How to be verbose.
+* Forcing_options:: Forcing options to a particular phase.
+* Many_versions_at_once:: Running several versions of the compiler at once.
+@end menu
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/configure b/web/glasgow/lit2x-0.16/literate/info-utils/configure
new file mode 100644
index 0000000000..ddd7422bca
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/configure
@@ -0,0 +1,429 @@
+#!/bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf.
+# Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create]
+# [--prefix=PREFIX] [--exec_prefix=PREFIX] [--with-PROGRAM] [TARGET]
+# Ignores all args except --srcdir, --prefix, --exec_prefix, and --no-create.
+
+trap 'rm -f conftest* core; exit 1' 1 3 15
+
+for arg
+do
+ # Handle --exec_prefix with a space before the argument.
+ if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix=
+ # Handle --host with a space before the argument.
+ elif test x$next_host = xyes; then next_host=
+ # Handle --prefix with a space before the argument.
+ elif test x$next_prefix = xyes; then prefix=$arg; next_prefix=
+ # Handle --srcdir with a space before the argument.
+ elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir=
+ else
+ case $arg in
+ -exec_prefix=* | --exec_prefix=* | --exec_prefi=* | --exec_pref=* | --exec_pre=* | --exec_pr=* | --exec_p=* | --exec_=* | --exec=* | --exe=* | --ex=* | --e=*)
+ exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -exec_prefix | --exec_prefix | --exec_prefi | --exec_pref | --exec_pre | --exec_pr | --exec_p | --exec_ | --exec | --exe | --ex | --e)
+ next_exec_prefix=yes ;;
+
+ -gas | --gas | --ga | --g) ;;
+
+ -host=* | --host=* | --hos=* | --ho=* | --h=*) ;;
+ -host | --host | --hos | --ho | --h)
+ next_host=yes ;;
+
+ -nfp | --nfp | --nf) ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no)
+ no_create=1 ;;
+
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ next_prefix=yes ;;
+
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*)
+ srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s)
+ next_srcdir=yes ;;
+
+ -with-* | --with-*) ;;
+
+ *) ;;
+ esac
+ fi
+done
+
+rm -f conftest*
+compile='${CC-cc} $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1'
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+unique_file=makeinfo.c
+
+# Makefile rules whose targets are searched for in VPATH need to use $<.
+# However, old makes do not support it, so we use a combination
+# construction in Makefile.in: `$file<'.
+# If srcdir is `.', we use sed to change that to `file' for old makes.
+# Otherwise, we use sed to change it to `$<'.
+# vpsub is the sed program, which changes `$file<' to one or the other.
+vpsub='s,\$\([-./a-zA-Z0-9_][-./a-zA-Z0-9_]*\)<,\1,g'
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ srcdirdefaulted=yes; srcdir=.
+ if test ! -r $unique_file; then srcdir=..; fi
+fi
+if test ! -r $srcdir/$unique_file; then
+ if test x$srcdirdefaulted = xyes; then
+ echo "configure: Can not find sources in \`.' or \`..'." 1>&2
+ else
+ echo "configure: Can not find sources in \`${srcdir}'." 1>&2
+ fi
+ exit 1
+fi
+if test $srcdir != .; then
+ vpsub='s,\$\([-./a-zA-Z0-9_][-./a-zA-Z0-9_]*\)<,\$<,g'
+fi
+# Preserve a srcdir of `.' to avoid automounter screwups with pwd.
+# But we can't avoid them for `..', to make subdirectories work.
+case $srcdir in
+ .|/*|~*) ;;
+ *) srcdir=`(cd $srcdir; pwd)` ;; # Make relative path absolute.
+esac
+
+
+# The Bourne shell writes "command not found" to /dev/tty, so if we get
+# a usage message on stderr, we have the program.
+#
+# ksh and zsh write "command not found" to stderr, but test -n does not
+# want any output if there is no program. So we use the `type' builtin
+# instead for them (and bash).
+if test "$RANDOM" = "$RANDOM"; then
+ checkfor='test -n "`$checkprog $checkargs 2>&1`"'
+else
+ checkfor='type $checkprog >/dev/null 2>&1'
+fi
+
+echo checking for gcc
+checkprog=gcc checkargs=''
+test -z "$CC" && eval $checkfor && CC='gcc '
+CC=${CC-cc}
+
+# Find out if we are using GNU C, under whatever name.
+cat <<EOF > conftest.c
+#ifdef __GNUC__
+ yes
+#endif
+EOF
+${CC-cc} -E conftest.c > conftest.out 2>&1
+if egrep yes conftest.out >/dev/null 2>&1; then
+ GCC=1 # For later tests.
+ CC="$CC -O"
+fi
+rm -f conftest*
+
+echo checking how to run the C preprocessor
+if test -z "$CPP"; then
+ CPP='${CC-cc} -E'
+ cat <<EOF > conftest.c
+
+#include <stdio.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ :
+else
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+
+if test -n "$GCC"; then
+ echo checking whether -traditional is needed
+ pattern="Autoconf.*'x'"
+ prog='#include <sgtty.h>
+Autoconf TIOCGETP'
+ cat <<EOF > conftest.c
+
+$prog
+EOF
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "$pattern" conftest.out >/dev/null 2>&1; then
+ need_trad=1
+fi
+rm -f conftest*
+
+
+ if test -z "$need_trad"; then
+ prog='#include <termio.h>
+Autoconf TCGETA'
+ cat <<EOF > conftest.c
+
+$prog
+EOF
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "$pattern" conftest.out >/dev/null 2>&1; then
+ need_trad=1
+fi
+rm -f conftest*
+
+ fi
+ test -n "$need_trad" && CC="$CC -traditional"
+fi
+
+echo checking for install
+# Make sure to not get the incompatible SysV /etc/install and
+# /usr/sbin/install, which might be in PATH before a BSD-like install.
+if test -z "$INSTALL"; then
+ saveifs="$IFS"; IFS="$IFS:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ case $dir in
+ /etc|/usr/sbin) ;;
+ *)
+ if test -f $dir/install; then
+ INSTALL="$dir/install -c"
+ INSTALL_PROGRAM='$(INSTALL)'
+ INSTALL_DATA='$(INSTALL) -m 644'
+ break
+ fi
+ ;;
+ esac
+ done
+ IFS="$saveifs"
+fi
+INSTALL=${INSTALL-cp}
+INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'}
+INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'}
+
+echo checking for AIX
+cat <<EOF > conftest.c
+
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "yes" conftest.out >/dev/null 2>&1; then
+ DEFS="$DEFS -D_ALL_SOURCE=1"
+fi
+rm -f conftest*
+
+
+echo checking for minix/config.h
+cat <<EOF > conftest.c
+
+#include <minix/config.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ MINIX=1
+fi
+rm -f conftest*
+
+# The Minix shell can't assign to the same variable on the same line!
+if test -n "$MINIX"; then
+ DEFS="$DEFS -D_POSIX_SOURCE=1"
+ DEFS="$DEFS -D_POSIX_1_SOURCE=2"
+ DEFS="$DEFS -D_MINIX=1"
+fi
+
+echo checking for POSIXized ISC
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ ISC=1 # If later tests want to check for ISC.
+ DEFS="$DEFS -D_POSIX_SOURCE=1"
+ if test -n "$GCC"; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+fi
+
+echo checking for sys/ptem.h
+cat <<EOF > conftest.c
+
+#include <sys/ptem.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ DEFS="$DEFS -DUSGr3=1"
+fi
+rm -f conftest*
+
+echo checking for ANSI C header files
+cat <<EOF > conftest.c
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ DEFS="$DEFS -DSTDC_HEADERS=1"
+fi
+rm -f conftest*
+
+echo checking for unistd.h
+cat <<EOF > conftest.c
+
+#include <unistd.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ DEFS="$DEFS -DHAVE_UNISTD_H=1"
+fi
+rm -f conftest*
+
+echo checking for BSD string and memory functions
+echo "#include <strings.h>
+main() { exit(0); } t() { rindex(0, 0); bzero(0, 0); }" > conftest.c
+if eval $compile; then
+ :
+else
+ DEFS="$DEFS -DUSG=1"
+fi
+rm -f conftest*
+
+echo checking for alloca.h
+cat <<EOF > conftest.c
+
+#include <alloca.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ DEFS="$DEFS -DHAVE_ALLOCA_H=1"
+fi
+rm -f conftest*
+
+decl="#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif
+#endif
+"
+echo checking for alloca
+echo "$decl
+main() { exit(0); } t() { char *p = (char *) alloca(1); }" > conftest.c
+if eval $compile; then
+ :
+else
+ alloca_missing=1
+fi
+rm -f conftest*
+
+if test -n "$alloca_missing"; then
+ SAVELIBS="$LIBS"
+ # Maybe alloca is in a different library.
+ if test -f /usr/ucblib/libucb.a; then
+ LIBS="$LIBS -L/usr/ucblib -lucb" trylib=-lucb # SVR4
+ elif test -f /lib/libPW.a; then
+ LIBS="$LIBS -lPW" trylib=-lPW # SVR2 and SVR3
+ fi
+ if test -n "$trylib"; then
+ alloca_missing=
+ echo checking for alloca in $trylib
+echo "$decl
+main() { exit(0); } t() { char *p = (char *) alloca(1); }" > conftest.c
+if eval $compile; then
+ :
+else
+ alloca_missing=1
+fi
+rm -f conftest*
+
+ fi
+ if test -n "$alloca_missing"; then
+ LIBS="$SAVELIBS" ALLOCA=alloca.o
+ fi
+fi
+
+if test -n "$prefix"; then
+ test -z "$exec_prefix" && exec_prefix='$(prefix)'
+ prsub="s,^prefix[ ]*=.*$,prefix = $prefix,"
+fi
+if test -n "$exec_prefix"; then
+ prsub="$prsub
+s,^exec_prefix[ ]*=.*$,exec_prefix = $exec_prefix,"
+fi
+
+trap 'rm -f config.status; exit 1' 1 3 15
+echo creating config.status
+rm -f config.status
+cat <<EOF > config.status
+#!/bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+trap 'rm -f Makefile; exit 1' 1 3 15
+CC='$CC'
+CPP='$CPP'
+INSTALL='$INSTALL'
+INSTALL_PROGRAM='$INSTALL_PROGRAM'
+INSTALL_DATA='$INSTALL_DATA'
+ALLOCA='$ALLOCA'
+LIBS='$LIBS'
+srcdir='$srcdir'
+DEFS='$DEFS'
+prefix='$prefix'
+exec_prefix='$exec_prefix'
+prsub='$prsub'
+vpsub='$vpsub'
+EOF
+cat <<\EOF >> config.status
+
+top_srcdir=$srcdir
+for file in Makefile; do
+ srcdir=$top_srcdir
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ dir=`echo $file|sed 's,/[^/][^/]*$,,'`
+ if test "$dir" != "$file"; then
+ test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
+ test ! -d $dir && mkdir $dir
+ fi
+ echo creating $file
+ rm -f $file
+ echo "# Generated automatically from `basename $file`.in by configure." > $file
+ sed -e "
+$vpsub
+$prsub
+s,@CC@,$CC,
+s,@CPP@,$CPP,
+s,@INSTALL@,$INSTALL,
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,
+s,@INSTALL_DATA@,$INSTALL_DATA,
+s,@ALLOCA@,$ALLOCA,
+s,@LIBS@,$LIBS,
+s,@srcdir@,$srcdir,
+s,@DEFS@,$DEFS," $top_srcdir/${file}.in >> $file
+done
+
+EOF
+chmod +x config.status
+test -n "$no_create" || ./config.status
+
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/configure.in b/web/glasgow/lit2x-0.16/literate/info-utils/configure.in
new file mode 100644
index 0000000000..0f220fcc84
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(makeinfo.c)
+AC_PROG_GCC
+AC_PROG_CPP
+AC_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_AIX
+AC_MINIX
+AC_ISC_POSIX
+AC_HEADER_CHECK(sys/ptem.h, AC_DEFINE(USGr3))
+AC_STDC_HEADERS
+AC_UNISTD_H
+AC_USG
+AC_ALLOCA
+AC_OUTPUT(Makefile)
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/default-nodes.texinfo b/web/glasgow/lit2x-0.16/literate/info-utils/default-nodes.texinfo
new file mode 100644
index 0000000000..27953e297d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/default-nodes.texinfo
@@ -0,0 +1,40 @@
+@setfilename default-nodes-example.info
+@node Top
+@chapter Introduction
+@menu
+* foo:: the foo node
+* bar:: the bar node
+* baz:: the baz node
+* yan:: Yet Another Node
+@end menu
+
+@node foo
+@section foo
+this is the foo node.
+
+@node bar
+@section Bar
+This is the Bar node.
+
+@menu
+* subzero:: A subsection of bar.
+* subone:: You thought I meant temperature?
+@end menu
+
+@node subzero
+@subsection subzero
+This is subsection subzero
+
+@node subone
+@subsection subone
+This is subsection subone
+
+@node baz
+@section Baz
+This is the Baz node.
+
+@node yan
+@section Yet Another Node
+
+Yes, this is yet another node.
+@bye
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/getopt.c b/web/glasgow/lit2x-0.16/literate/info-utils/getopt.c
new file mode 100644
index 0000000000..5b9970537a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/getopt.c
@@ -0,0 +1,681 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif /* sparc */
+#endif /* not __GNUC__ */
+
+/* partain: to go w/ "make world" */
+#if defined(SYSV)
+#define USG 1
+#endif
+/* end partain */
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#undef alloca
+#include <stdlib.h>
+#include <string.h>
+#else /* Not GNU C library. */
+#define __alloca alloca
+#endif /* GNU C library. */
+
+
+#ifndef __STDC__
+#define const
+#endif
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+ long-named option. Because this is not POSIX.2 compliant, it is
+ being phased out. */
+#define GETOPT_COMPAT
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+#include <string.h>
+#define my_index strchr
+#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (string, chr)
+ char *string;
+ int chr;
+{
+ while (*string)
+ {
+ if (*string == chr)
+ return string;
+ string++;
+ }
+ return 0;
+}
+
+static void
+my_bcopy (from, to, size)
+ char *from, *to;
+ int size;
+{
+ int i;
+ for (i = 0; i < size; i++)
+ to[i] = from[i];
+}
+#endif /* GNU C library. */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
+ char **temp = (char **) __alloca (nonopts_size);
+
+ /* Interchange the two blocks of data in ARGV. */
+
+ my_bcopy (&argv[first_nonopt], temp, nonopts_size);
+ my_bcopy (&argv[last_nonopt], &argv[first_nonopt],
+ (optind - last_nonopt) * sizeof (char *));
+ my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int option_index;
+
+ optarg = 0;
+
+ /* Initialize the internal data when the first call is made.
+ Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ if (optind == 0)
+ {
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (getenv ("POSIXLY_CORRECT") != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Now skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* Special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Start decoding its characters. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ if (longopts != NULL
+ && ((argv[optind][0] == '-'
+ && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ ))
+ {
+ const struct option *p;
+ char *s = nextchar;
+ int exact = 0;
+ int ambig = 0;
+ const struct option *pfound = NULL;
+ int indfound;
+
+ while (*s && *s != '=')
+ s++;
+
+ /* Test all options for either exact match or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp (p->name, nextchar, s - nextchar))
+ {
+ if (s - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*s)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = s + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (c < 040 || c >= 0177)
+ fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+ }
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = 0;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], c);
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+/* partain:
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+*/
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/getopt.h b/web/glasgow/lit2x-0.16/literate/info-utils/getopt.h
new file mode 100644
index 0000000000..4d8b31ca59
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/getopt.h
@@ -0,0 +1,121 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+enum _argtype
+{
+ no_argument,
+ required_argument,
+ optional_argument
+};
+
+#if __STDC__
+/* partain: extern int getopt (int argc, char *const *argv, const char *shortopts); */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+/* partain: extern int getopt (); */
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/getopt1.c b/web/glasgow/lit2x-0.16/literate/info-utils/getopt1.c
new file mode 100644
index 0000000000..ae7930d058
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/getopt1.c
@@ -0,0 +1,158 @@
+/* Getopt for GNU.
+ Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef LIBC
+/* For when compiled as part of the GNU C library. */
+#include <ansidecl.h>
+#endif
+
+#include "getopt.h"
+
+#ifndef __STDC__
+#define const
+#endif
+
+#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) || defined (LIBC)
+#include <stdlib.h>
+#else /* STDC_HEADERS or __GNU_LIBRARY__ */
+char *getenv ();
+#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
+
+#if !defined (NULL)
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/info.1 b/web/glasgow/lit2x-0.16/literate/info-utils/info.1
new file mode 100644
index 0000000000..f49dc2982d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/info.1
@@ -0,0 +1,101 @@
+.TH INFO 1 "26 June 1988"
+.SH NAME
+info \- Hierarchal information tree peruser
+.SH SYNOPSIS
+.B info
+[ -d info-directory-path ]
+[ -f info-file ]
+[ -o dump-file ]
+[ -n node-name ]
+[ menu-name ...]
+.SH DESCRIPTION
+.I Info
+is an interactive tool for reading the on-line documentation made from
+texinfo files. There are almost no differences between
+.I Info
+and the `M-x info' command from within
+.I Emacs.
+.I Info
+is a standalone program, and can be invoked from the command line. The
+.I menu-name
+(s) are the series of menu options that you wish to follow from the main menu.
+For example, to get info about using buffers in Emacs, you might type `info
+emacs buffers'. Try it, you'll like it.
+.PP
+.SH OPTIONS
+
+.IP -o
+dumps the contents of the node that you have specified, so that
+you can do with it what you please. Note that you can print the node that you
+are currently looking at with `C-p' from within
+.I Info
+, so it isn't clear what you want to do with the output from -o.
+.PP
+.IP -d
+is a quick way for you to temporarily change the path searched by
+.I Info
+when it starts up. You can also set the environment variable
+"INFO_DIRECTORY_PATHS" to a list of colon-separated directory names.
+.PP
+.IP -f
+is for specifying which Info file to load. Normally,
+.I Info
+looks for the file `dir' in the info search path, and goes to node `Top' in
+that file. The `dir' file contains a menu whose items all point to info
+files. If the info file you wish to view is not in that menu, you can say
+`info -f info-filename', and that file specifically will be used.
+.PP
+.IP -n
+sets the initial node to look for. This allows you to read an info file that
+doesn't have a `Top' node.
+.PP
+In order to find out more about
+.I Info
+, type `info', and press "h". (You will be reminded of your options when you
+first start using the
+.I Info
+program anyway.)
+.PP
+You are welcome to submit documentation for use in
+.I Info
+, and in fact, whole-heartedly encouraged. Remember to read the node on
+.I texinfo
+before submitting the text though, since it will likely only be accepted in that format.
+.PP
+
+
+.SH BUGS
+.PP
+The display on slow terminals is pretty gosh darn slow. This is due to the
+crufty implementation, and will be fixed as soon as someone complains
+about it, or maybe before.
+.PP
+There is no specific X windows support. X windows should be supported, and
+we should allow `hot spots' in the text of nodes, which could point to
+other nodes.
+.PP
+An info file without a `Top' node can only be viewed if you know the name of a
+node inside of it. Maybe the
+.I Makeinfo
+program should automatically make a menu of top-level nodes and place it in a
+node called `Top' if there is no such node in the info file.
+.SH FILES
+.br
+The default search path for a bare bones Info is
+.br
+".:/usr/gnu/info:/usr/local/emacs/info:/usr/local/lib/emacs/info"
+.PP
+You can change this with the INFOPATH environment variable.
+.SH SEE ALSO
+makeinfo (1)
+.SH ACKNOWLEDGEMENT
+Richard Stallman invented the Info concept many moons ago, even before
+the advent of hypertext. He also suggested that I write this program.
+.SH AUTHOR
+Brian J. Fox (bfox@ai.mit.edu)
+.br
+Free Software Foundation
+.br
+Cambridge, MA
+.br
+September, 1987
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/info.c b/web/glasgow/lit2x-0.16/literate/info-utils/info.c
new file mode 100644
index 0000000000..941955c89c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/info.c
@@ -0,0 +1,4744 @@
+/* info -- a stand-alone Info program.
+
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Info.
+
+ GNU Info is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor accepts
+ responsibility to anyone for the consequences of using it or for
+ whether it serves any particular purpose or works at all, unless he
+ says so in writing. Refer to the GNU Emacs General Public License
+ for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ GNU Info, but only under the conditions described in the GNU Emacs
+ General Public License. A copy of this license is supposed to
+ have been given to you along with GNU Emacs so you can know your
+ rights and responsibilities. It should be in a file named COPYING.
+ Among other things, the copyright notice and this notice must be
+ preserved on all copies. */
+
+/* This is GNU Info:
+
+ Version 1.44 (Change "major_version" and "minor_version" below.)
+ Fri Feb 7 1992
+*/
+
+/* partain: to go w/ "make world" */
+#if defined(SYSV)
+#define USG 1
+#endif
+/* end partain */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <ctype.h>
+#include "getopt.h"
+
+#if defined (USG)
+ struct passwd *getpwnam ();
+# include <fcntl.h>
+# include <termio.h>
+# include <string.h>
+
+# if defined (USGr3)
+# if !defined (M_XENIX)
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# undef TIOCGETC
+# else /* M_XENIX */
+# define tchars tc
+# include <sys/ttold.h>
+# endif /* M_XENIX */
+# endif /* USGr3 */
+# define bcopy(source, dest, count) memcpy(dest, source, count)
+ char *index(s,c) char *s; { char *strchr(); return strchr(s,c); }
+ char *rindex(s,c) char *s; { char *strrchr(); return strrchr(s,c); }
+#else /* !USG */
+# include <sys/file.h>
+# include <sgtty.h>
+# include <strings.h>
+#endif /* USG */
+
+#if !defined (DEFAULT_INFOPATH)
+# define DEFAULT_INFOPATH \
+ ".:/usr/gnu/info:/usr/local/emacs/info:/usr/local/lib/emacs/info"
+#endif /* !DEFAULT_INFOPATH */
+
+typedef struct nodeinfo {
+ char *filename;
+ char *nodename;
+ int pagetop;
+ int nodetop;
+ struct nodeinfo *next;
+} NODEINFO;
+
+typedef struct indirectinfo {
+ char *filename;
+ int first_byte;
+} INDIRECT_INFO;
+
+typedef int Function ();
+#define VOID_SIGHANDLER
+#if defined (VOID_SIGHANDLER)
+# define SigHandler void
+#else
+# define SigHandler int
+#endif /* !VOID_SIGHANDLER */
+#define barf(msg) fprintf(stderr, "%s\n", msg)
+
+/* Some character stuff. */
+#define control_character_threshold 0x020 /* smaller than this is control */
+#define meta_character_threshold 0x07f /* larger than this is Meta. */
+#define control_character_bit 0x40 /* 0x000000, must be off. */
+#define meta_character_bit 0x080 /* x0000000, must be on. */
+
+#define info_separator_char '\037'
+#define start_of_node_string "\037"
+
+#ifdef CTRL
+#undef CTRL
+#endif
+
+#define CTRL(c) ((c) & (~control_character_bit))
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) to_upper(((c)|control_character_bit))
+
+#ifndef to_upper
+#define to_upper(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) - 32)
+#define to_lower(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) + 32)
+#endif
+
+#define CTRL_P(c) ((unsigned char) (c) < control_character_threshold)
+#define META_P(c) ((unsigned char) (c) > meta_character_threshold)
+
+#define NEWLINE '\n'
+#define RETURN CTRL('M')
+#define DELETE 0x07f
+#define TAB '\t'
+#define ABORT_CHAR CTRL('G')
+#define PAGE CTRL('L')
+#define SPACE 0x020
+#define ESC CTRL('[')
+#define control_display_prefix '^'
+
+#define TAG_TABLE_END_STRING "\037\nEND TAG TABLE"
+#define TAG_TABLE_BEG_STRING "\nTAG TABLE:\n"
+#define NODE_ID "Node:"
+#define NNODENAME 4 /* Default amount to grow nodename list by. */
+#define FILENAME_LEN 256
+#define NODENAME_LEN 256
+#define STRING_SIZE 256
+#define nodeend_sequence "\n\037"
+
+#define whitespace(c) ((c) == ' ' || (c) == '\t')
+#define cr_whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
+
+/* All right, some windows stuff. */
+
+typedef struct {
+ /* Absolute x and y coordinates for usable portion of this window. */
+ int left, top, right, bottom;
+ /* Absolute cursor position in this window. */
+ int ch, cv;
+} WINDOW;
+
+typedef struct _wind_list {
+ int left, top, right, bottom;
+ int ch, cv;
+ struct _wind_list *next_window;
+} WINDOW_LIST;
+
+WINDOW the_window = {0, 0, 80, 24, 0, 0};
+WINDOW_LIST *window_stack = (WINDOW_LIST *)NULL;
+WINDOW terminal_window = {0, 0, 80, 24, 0, 0};
+
+/* Not really extern, but defined later in this file. */
+extern WINDOW echo_area;
+void *xmalloc (), *xrealloc ();
+char *getenv (), *next_info_file (), *opsys_filename ();
+int build_menu (), find_menu_node ();
+void swap_filestack (), pop_filestack ();
+
+/* A crock, this should be done in a different way. */
+#define MAX_INDIRECT_FILES 100
+
+/* The info history list. */
+NODEINFO *Info_History = NULL;
+
+/* ?Can't have more than xx files in the indirect list? */
+INDIRECT_INFO indirect_list[MAX_INDIRECT_FILES];
+
+/* The filename of the currently loaded info file. */
+char current_info_file[FILENAME_LEN];
+
+/* The nodename of the node the user is looking at. */
+char current_info_node[NODENAME_LEN];
+
+/* The last file actually loaded. Not the same as current info file. */
+char last_loaded_info_file[FILENAME_LEN];
+
+/* Offsets in info_file of top and bottom of current_info_node. */
+int nodetop, nodebot;
+
+/* Number of lines in this node. */
+int nodelines;
+
+/* Buffer for the info file. */
+char *info_file = NULL;
+
+/* Length of the above buffer. */
+int info_buffer_len;
+
+/* Pointer to the start of a tag table, or NULL to show none. */
+char *tag_table = NULL;
+
+/* Length of the above buffer. */
+int tag_buffer_len;
+
+/* Non-zero means that the tag table is indirect. */
+int indirect = 0;
+int indirect_top;
+
+/* Offset in the buffer of the current pagetop. */
+int pagetop;
+
+/* Offset in the buffer of the last displayed character. */
+int pagebot = 0;
+
+/* If non-NULL, this is a colon separated list of directories to search
+ for a specific info file. The user places this variable into his or
+ her environment. */
+char *infopath = NULL;
+
+/* If filled, the name of a file to write to. */
+char dumpfile[FILENAME_LEN] = "";
+
+/* This is the command to print a node. A default value is compiled in,
+ or it can be found from the environment as $INFO_PRINT_COMMAND. */
+char *print_command;
+
+/* Non-zero means forst redisplay before prompt for the next command. */
+int window_bashed = 0;
+
+/* **************************************************************** */
+/* */
+/* Getting Started. */
+/* */
+/* **************************************************************** */
+
+/* Begin the Info session. */
+
+/* Global is on until we are out of trouble. */
+int totally_inhibit_errors = 1;
+
+/* Non-zero means print version info only. */
+int version_flag = 0;
+
+/* The major and minor versions of Info. */
+int major_version = 1;
+int minor_version = 44;
+
+struct option long_options[] = {
+ { "directory", 1, 0, 'd' },
+ { "node", 1, 0, 'n' },
+ { "file", 1, 0, 'f' },
+ { "output", 1, 0, 'o' },
+ { "version", 0, &version_flag, 1 },
+ {NULL, 0, NULL, 0}
+};
+
+#define savestring(x) (char *) strcpy ((char *) xmalloc (1 + strlen (x)), (x))
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c, ind, no_such_node = 0;
+ char filename[FILENAME_LEN];
+ char *nodename;
+ char **nodenames;
+ int nodenames_size, nodenames_index;
+ char *ptr, *env_infopath, *env_print_command;
+
+ nodenames_index = 0;
+ nodenames = (char **) xmalloc ((nodenames_size = 1) * sizeof (char *));
+ nodenames[0] = (char *)NULL;
+
+ env_infopath = getenv ("INFOPATH");
+ env_print_command = getenv ("INFO_PRINT_COMMAND");
+
+ filename[0] = '\0';
+
+ if (env_infopath && *env_infopath)
+ infopath = savestring (env_infopath);
+ else
+ infopath = savestring (DEFAULT_INFOPATH);
+
+ if (env_print_command && *env_print_command)
+ print_command = savestring (env_print_command);
+ else
+ print_command = savestring (INFO_PRINT_COMMAND);
+
+ while ((c = getopt_long (argc, argv, "d:n:f:o:", long_options, &ind)) != EOF)
+ {
+ if (c == 0 && long_options[ind].flag == 0)
+ c = long_options[ind].val;
+ switch (c)
+ {
+ case 0:
+ break;
+
+ case 'd':
+ free (infopath);
+ infopath = savestring (optarg);
+ break;
+
+ case 'n':
+
+ if (nodenames_index + 2 > nodenames_size)
+ nodenames = (char **)
+ xrealloc (nodenames, (nodenames_size += 10) * sizeof (char *));
+
+ nodenames[nodenames_index++] = optarg;
+ nodenames[nodenames_index] = (char *)NULL;
+ break;
+
+ case 'f':
+ strncpy (filename, optarg, FILENAME_LEN);
+ break;
+
+ case 'o':
+ strncpy (dumpfile, optarg, FILENAME_LEN);
+ break;
+
+ default:
+ usage ();
+ }
+ }
+
+ /* If the user specified `--version' then simply show the version
+ info at this time and exit. */
+ if (version_flag)
+ {
+ show_version_info (stdout);
+ exit (0);
+ }
+
+ /* Okay, flags are parsed. Get possible Info menuname. */
+
+ if (*filename && (ptr = rindex (filename,'/')) != NULL )
+ {
+ /* Add filename's directory to path. */
+ char *temp;
+
+ temp = (char *) xmalloc (2 + strlen (filename) + strlen (infopath));
+ strncpy (temp, filename, ptr - filename);
+ sprintf (temp + (ptr - filename), ":%s", infopath);
+ free (infopath);
+ infopath = temp;
+ }
+
+ /* Start with DIR or whatever was specified. */
+ if (!get_node (filename, (nodenames[0] == NULL) ? "Top" : nodenames[0], 0))
+ {
+ if (filename[0])
+ {
+ fprintf (stderr, "Try just plain `info'.\n");
+ exit (1);
+ }
+ else
+ {
+ strcpy (filename, "DIR");
+
+ if (!get_node ((char *)NULL, (char *)NULL, 1))
+ {
+ fprintf (stderr,
+ "%s: Cannot find \"%s\", anywhere along the search ",
+ argv[0], filename);
+ fprintf (stderr, "path of\n\"%s\".\n", infopath);
+ exit (1);
+ }
+ }
+ }
+
+ totally_inhibit_errors = 0;
+
+ for (ind = 1 ; ind < nodenames_index ; ind++)
+ get_node (filename, nodenames[ind], 0);
+
+ nodename = nodenames[nodenames_index > 0 ? nodenames_index - 1 : 0];
+ if (!nodename)
+ {
+ nodename = (char *) xmalloc (NODENAME_LEN);
+ *nodename = '\0';
+ }
+
+ if (optind != argc)
+ {
+ while (optind != argc)
+ {
+ if (!build_menu ())
+ {
+ display_error ("There is no menu in node \"%s\"",
+ current_info_node );
+ no_such_node++;
+ break;
+ }
+ else if (!find_menu_node (argv[optind], nodename))
+ {
+ display_error
+ ("There is no menu entry for \"%s\" in node \"%s\"",
+ argv[optind], nodename );
+ no_such_node++;
+ break;
+ }
+ else if (!get_node ((char *)NULL, nodename, 0))
+ {
+ no_such_node++;
+ break;
+ }
+ else
+ {
+#if 1
+ /* RMS says not to type this stuff out because he expects
+ programs to call Info instead of interactive users. */
+ printf ("%s.. ",argv[optind]);
+ fflush (stdout);
+#endif
+ optind++;
+ }
+ }
+ }
+
+ /* If we are outputting to a file, and the node was not found, exit. */
+ if (no_such_node && dumpfile[0])
+ exit (1);
+ else
+ begin_info_session ();
+
+ exit (0);
+}
+
+usage ()
+{
+ fprintf (stderr,"%s\n%s\n%s\n%s\n",
+"Usage: info [-d dir-path] [-f info-file] [-n node-name -n node-name ...]",
+" [-o output-file] [--directory dir-path] [--file info-file]",
+" [--node node-name --node node-name ...] [--version]",
+" [--output output-file] [menu-selection...]");
+ exit (1);
+}
+
+/* Print the version of info to standard output. */
+show_version_info (stream)
+ FILE *stream;
+{
+ fprintf (stream, "GNU Info version %d.%d\n", major_version, minor_version);
+ fflush (stream);
+}
+
+#if defined (SIGTSTP)
+Function *old_tstp;
+Function *old_ttou, *old_ttin;
+#endif /* SIGTSTP */
+
+#if defined (SIGWINCH)
+Function *old_winch;
+#endif /* SIGWINCH */
+
+/* Start using Info. */
+begin_info_session ()
+{
+ SigHandler info_signal_handler ();
+
+ /* If the user just wants to dump the node, then do that. */
+ if (dumpfile[0])
+ {
+ dump_current_node (dumpfile);
+ exit (0);
+ }
+
+ init_terminal_io ();
+
+ /* Install handlers for restoring/breaking the screen. */
+
+ install_signals ();
+ new_echo_area ();
+
+ print_string ("Welcome to Info! Type \"?\" for help. ");
+ close_echo_area ();
+ toploop ();
+ goto_xy (the_window.left, the_window.bottom + 1);
+ restore_io ();
+}
+
+/* What to do before processing a stop signal. */
+before_stop_signal ()
+{
+ restore_io ();
+}
+
+/* What to do after processing a stop signal. */
+after_stop_signal ()
+{
+ clear_screen ();
+ display_page ();
+ goto_xy (the_window.ch, the_window.cv);
+ opsys_init_terminal ();
+}
+
+/* partain: moved these here */
+char *widest_line;
+
+int terminal_columns; /* {tc_int, "co" */
+int terminal_rows; /* {tc_int, "li" */
+
+/* Do the right thing with this signal. */
+SigHandler
+info_signal_handler (sig)
+ int sig;
+{
+ switch (sig)
+ {
+#if defined (SIGTSTP)
+ case SIGTSTP:
+ case SIGTTOU:
+ case SIGTTIN:
+ before_stop_signal ();
+ signal (sig, SIG_DFL);
+#if !defined (USG)
+ sigsetmask (sigblock (0) & ~sigmask (sig));
+#endif /* !USG */
+ kill (getpid (), sig);
+ after_stop_signal ();
+ signal (sig, info_signal_handler);
+ break;
+#endif /* SIGTSTP */
+
+#if defined (SIGWINCH)
+ case SIGWINCH:
+ /* Window has changed. Get the size of the new window, and rebuild our
+ window chain. */
+ {
+ int display_page ();
+ extern char *widest_line;
+ extern WINDOW terminal_window;
+ extern WINDOW_LIST *window_stack;
+ extern int terminal_rows, terminal_columns;
+ int delta_width, delta_height, right, bottom;
+
+ right = get_terminal_columns ();
+ bottom = get_terminal_rows ();
+
+ delta_width = right - terminal_columns;
+ delta_height = bottom - terminal_rows;
+
+ terminal_columns = right;
+ terminal_rows = bottom;
+
+ /* Save current window, whatever it is. */
+ push_window ();
+
+ /* Change the value of the widest_line. */
+ free (widest_line);
+ widest_line = (char *) xmalloc (right);
+
+ /* Make the new window. Map over all windows in window list. */
+ {
+ WINDOW_LIST *wind = window_stack;
+ extern WINDOW modeline_window;
+
+ while (wind != (WINDOW_LIST *)NULL)
+ {
+ adjust_wind ((WINDOW *)wind, delta_width, delta_height);
+ wind = wind->next_window;
+ }
+
+ /* Adjust the other windows that we know about. */
+ adjust_wind (&terminal_window, delta_width, delta_height);
+ adjust_wind (&echo_area, delta_width, delta_height);
+ adjust_wind (&modeline_window, delta_width, delta_height);
+ }
+
+ /* Clear and redisplay the entire terminal window. */
+ set_window (&terminal_window);
+ clear_screen ();
+
+ /* Redisplay the contents of the screen. */
+ with_output_to_window (&terminal_window, display_page);
+
+ /* Get back the current window. */
+ pop_window ();
+ }
+ break;
+#endif /* SIGWINCH */
+
+ case SIGINT:
+ restore_io ();
+ exit (1);
+ break;
+ }
+}
+
+install_signals ()
+{
+#if defined (SIGTSTP)
+ old_tstp = (Function *) signal (SIGTSTP, info_signal_handler);
+ old_ttou = (Function *) signal (SIGTTOU, info_signal_handler);
+ old_ttin = (Function *) signal (SIGTTIN, info_signal_handler);
+#endif /* SIGTSTP */
+
+#if defined (SIGWINCH)
+ old_winch = (Function *) signal (SIGWINCH, info_signal_handler);
+#endif /* SIGWINCH */
+
+ signal (SIGINT, info_signal_handler);
+}
+
+adjust_wind (wind, delta_width, delta_height)
+ WINDOW *wind;
+ int delta_width, delta_height;
+{
+ wind->right += delta_width;
+ wind->bottom += delta_height;
+ wind->ch += delta_width;
+ wind->cv += delta_height;
+
+ /* Ugly hack to fix busted windows code. If the window we are adjusting
+ already has a TOP offset, then adjust that also. */
+ if (wind->top)
+ wind->top += delta_height;
+}
+
+/* **************************************************************** */
+/* */
+/* Completing Things */
+/* */
+/* **************************************************************** */
+
+typedef struct completion_entry
+{
+ char *identifier;
+ char *data;
+ struct completion_entry *next;
+} COMP_ENTRY;
+
+/* The linked list of COMP_ENTRY structures that you create. */
+COMP_ENTRY *completion_list = (COMP_ENTRY *) NULL;
+
+/* The vector of COMP_ENTRY pointers that COMPLETE returns. */
+COMP_ENTRY **completions = NULL;
+
+/* The number of elements in the above vector. */
+int completion_count;
+
+/* Initial size of COMPLETIONS array. */
+#define INITIAL_COMPLETIONS_CORE_SIZE 200
+
+/* Current size of the completion array in core. */
+int completions_core_size = 0;
+
+/* Ease the typing task. Another name for the I'th
+ IDENTIFIER of COMPLETIONS. */
+#define completion_id(i) ((completions[(i)])->identifier)
+
+/* The number of completions that can be present before the help
+ function starts asking you about whether it should print them
+ all or not. */
+int completion_query_threshold = 100;
+
+free_completion_list ()
+{
+ COMP_ENTRY *temp;
+ while (completion_list)
+ {
+ temp = completion_list;
+
+ if (completion_list->identifier)
+ free (completion_list->identifier);
+
+ if (completion_list->data)
+ free (completion_list->data);
+
+ completion_list = completion_list->next;
+ free (temp);
+ }
+}
+
+/* Add a single completion to COMPLETION_LIST.
+ IDENTIFIER is the string that the user should type.
+ DATA should just be a pointer to some random data that you wish to
+ have associated with the identifier, but I'm too stupid for that, so
+ it must be a string as well. This allocates the space for the strings
+ so you don't necessarily have to. */
+add_completion (identifier, data)
+ char *identifier, *data;
+{
+ COMP_ENTRY *temp = (COMP_ENTRY *) xmalloc (sizeof (COMP_ENTRY));
+
+ temp->identifier = (char *) xmalloc (strlen (identifier) + 1);
+ strcpy (temp->identifier, identifier);
+
+ temp->data = (char *) xmalloc (strlen (data) + 1);
+ strcpy (temp->data, data);
+
+ temp->next = completion_list;
+ completion_list = temp;
+}
+
+/* Function for reading a line. Supports completion on COMPLETION_LIST
+ if you pass COMPLETING as non-zero. Prompt is either a prompt or
+ NULL, LINE is the place to store the characters that are read.
+ LINE may start out already containing some characters; if so, they
+ are printed. MAXCHARS tells how many characters can fit in the
+ buffer at LINE. readline () returns zero if the user types the
+ abort character. LINE is returned with a '\0' at the end, not a '\n'. */
+int
+readline (prompt, line, maxchars, completing)
+ char *prompt, *line;
+ int maxchars;
+ int completing;
+{
+ int character;
+ int readline_ch, readline_cv;
+ int current_len = strlen (line);
+ int just_completed = 0; /* Have we just done a completion? */
+ int meta_flag = 0;
+
+ new_echo_area ();
+
+ if (prompt)
+ print_string ("%s", prompt);
+
+ readline_ch = the_window.ch;
+ readline_cv = the_window.cv;
+
+ print_string ("%s", line);
+
+ while (1)
+ {
+ line[current_len] = '\0';
+ goto_xy (readline_ch, readline_cv);
+ print_string ("%s", line);
+ clear_eol ();
+
+ if (just_completed)
+ just_completed--;
+
+ character = blink_cursor ();
+ if (meta_flag)
+ {
+ character = META (character);
+ meta_flag = 0;
+ }
+
+ if (META_P (character))
+ character = META (to_upper (UNMETA (character)));
+
+ switch (character)
+ {
+ case EOF:
+ character = '\n';
+
+ case ESC:
+ meta_flag++;
+ break;
+
+ case META (DELETE):
+ case CTRL ('W'):
+ while (current_len && line[current_len] == SPACE)
+ current_len--;
+
+ if (!current_len)
+ break;
+
+ while (current_len && line[current_len] != SPACE)
+ current_len--;
+
+ break;
+
+ case CTRL ('U'):
+ current_len = 0;
+ break;
+
+ case '\b':
+ case 0x07f:
+ if (current_len)
+ current_len--;
+ else
+ ding ();
+ break;
+
+ case '\n':
+ case '\r':
+ if (completing)
+ {
+ extern int completion_count;
+
+ try_complete (line);
+
+ if (completion_count >= 1)
+ {
+ close_echo_area ();
+ return (1);
+ }
+ else
+ {
+ current_len = strlen (line);
+ break;
+ }
+ }
+ else
+ {
+ close_echo_area ();
+ return (1);
+ }
+
+ case ABORT_CHAR:
+ ding ();
+
+ if (current_len)
+ {
+ current_len = 0;
+ }
+ else
+ {
+ close_echo_area ();
+ clear_echo_area ();
+ return (0);
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ case '?':
+ if (completing)
+ {
+ extern int completion_count;
+
+ if (character == '?' || just_completed)
+ {
+ help_possible_completions (line);
+ break;
+ }
+ else
+ {
+ char temp_line[NODENAME_LEN];
+ strcpy (temp_line, line);
+ try_complete (line); just_completed = 2;
+ if (completion_count != 1 && character == SPACE)
+ {
+ if (strcmp (temp_line, line) == 0)
+ {
+ line[current_len] = SPACE;
+ line[current_len + 1] = '\0';
+ strcpy (temp_line, line);
+ try_complete (line);
+ if (completion_count == 0)
+ {
+ line[current_len] = '\0';
+ ding ();
+ }
+ }
+ }
+ current_len = strlen (line);
+ if (completion_count == 0)
+ ding ();
+ break;
+ }
+ }
+ /* Do *NOT* put anything in-between the completing cases and
+ the default: case. No. Because the SPC, TAB and `?' get
+ treated as normal characters by falling through the
+ "if (completing)" test above. */
+ default:
+ if (!CTRL_P (character) &&
+ !META_P (character) &&
+ current_len < maxchars)
+ line[current_len++] = character;
+ else
+ ding ();
+ }
+ }
+}
+
+/* Initialize whatever the completer is using. */
+init_completer ()
+{
+ if (completions_core_size != INITIAL_COMPLETIONS_CORE_SIZE)
+ {
+ if (completions)
+ free (completions);
+
+ completions = (COMP_ENTRY **)
+ xmalloc ((sizeof (COMP_ENTRY *))
+ * (completions_core_size = INITIAL_COMPLETIONS_CORE_SIZE));
+ }
+ completion_count = 0;
+}
+
+/* Reverse the completion list passed in LIST, and
+ return a pointer to the new head. */
+COMP_ENTRY *
+reverse_list (list)
+ COMP_ENTRY *list;
+{
+ COMP_ENTRY *next;
+ COMP_ENTRY *prev = (COMP_ENTRY *) NULL;
+
+ while (list)
+ {
+ next = list->next;
+ list->next = prev;
+ prev = list;
+ list = next;
+ }
+ return (prev);
+}
+
+/* Remember the possible completion passed in POINTER on the
+ completions list. */
+remember_completion (pointer)
+ COMP_ENTRY *pointer;
+{
+ if (completion_count == completions_core_size)
+ {
+ COMP_ENTRY **temp = (COMP_ENTRY **)
+ realloc (completions, ((sizeof (COMP_ENTRY *))
+ * (completions_core_size +=
+ INITIAL_COMPLETIONS_CORE_SIZE)));
+ if (!temp)
+ {
+ display_error ("Too many completions (~d)! Out of core!",
+ completion_count);
+ return;
+ }
+ else
+ completions = temp;
+ }
+ completions[completion_count++] = pointer;
+}
+
+/* Complete TEXT from identifiers in LIST. Place the resultant
+ completions in COMPLETIONS, and the number of completions in
+ COMPLETION_COUNT. Modify TEXT to contain the least common
+ denominator of all the completions found. */
+int
+complete (text, list)
+ char *text;
+ COMP_ENTRY *list;
+{
+ int low_match, i, idx;
+ int string_length = strlen (text);
+
+ init_completer ();
+ low_match = 100000; /* Some large number. */
+
+ while (list)
+ {
+ if (strnicmp (text, list->identifier, string_length) == 0)
+ remember_completion (list);
+ list = list->next;
+ }
+
+ if (completion_count == 0)
+ return (0);
+
+ if (completion_count == 1)
+ { /* One completion */
+ strcpy (text, completion_id (0));
+ return (1);
+ }
+
+ /* Else find the least common denominator */
+
+ idx = 1;
+
+ while (idx < completion_count)
+ {
+ int c1, c2;
+ for (i = 0;
+ (c1 = to_lower (completion_id (idx - 1)[i])) &&
+ (c2 = to_lower (completion_id (idx)[i]));
+ i++)
+ if (c1 != c2)
+ break;
+
+ if (low_match > i)
+ low_match = i;
+ idx++;
+ }
+
+ strncpy (text, completion_id (0), low_match);
+ text[low_match] = '\0';
+ return (1);
+}
+
+/* Complete TEXT from the completion structures in COMPLETION_LIST. */
+int
+try_complete (text)
+ char *text;
+{
+ return (complete (text, completion_list));
+}
+
+/* The function that prints out the possible completions. */
+help_possible_completions (text)
+ char *text;
+{
+ char temp_string[2000];
+
+ goto_xy (the_window.left, the_window.top);
+ strcpy (temp_string, text);
+ try_complete (temp_string);
+
+ open_typeout ();
+
+ if (completion_count == 0)
+ {
+ print_string ("There are no possible completions.\n");
+ goto print_done;
+ }
+
+ if (completion_count == 1)
+ {
+ print_string
+ ("The only possible completion of what you have typed is:\n\n");
+ print_string ("%s", completion_id(0));
+ goto print_done;
+ }
+
+ if (completion_count >= completion_query_threshold)
+ {
+ print_string
+ ("\nThere are %d completions. Do you really want to see them all",
+ completion_count);
+
+ if (!get_y_or_n_p ())
+ return;
+ }
+
+ print_string ("\nThe %d completions of what you have typed are:\n\n",
+ completion_count);
+
+ {
+ int idx = 0;
+ int counter = 0;
+ int columns = (the_window.right - the_window.left) / 30;
+
+ while (idx < completion_count)
+ {
+ if (counter == columns)
+ {
+ charout ('\n');
+ counter = 0;
+ }
+ indent_to (counter * 30);
+ print_string ("%s", completion_id (idx));
+ counter++;
+ idx++;
+ }
+ }
+
+print_done:
+ print_string ("\n\n-----------------\n");
+ close_typeout ();
+}
+
+/* Return the next file that should be searched, or NULL if we are at the end
+ of the info file. If the FILE argument is provided, begin the search there,
+ if REWIND is non-zero start the search at the beginning of the list.
+
+ The list is the one built by an indirect tag table, on the supposition
+ that those files form a logical set to search if we are in one of them.
+ If no such list is current (either it doesn't exist, or FILE isn't on
+ it) the search list is set to be last_loaded_info_file */
+char *
+next_info_file (file, rewind)
+ char *file; /* file to set `next' to. May be NULL. */
+ int rewind; /* should I rewind the file list? */
+{
+ static int index = -1;
+
+ if (file != NULL)
+ {
+ char *ptr = rindex (file,'/');
+
+ if (ptr != NULL)
+ file = ptr + 1;
+
+ for (index = 0;
+ index < MAX_INDIRECT_FILES &&
+ indirect_list[index].filename != (char *)NULL;
+ index++)
+ {
+ if (strcmp (file, indirect_list[index].filename) == 0)
+ return (file);
+ }
+
+ /* OK, we are not on the current indirect_list. This means that
+ we have switched to another node that has no indirect list,
+ so forget the old one. */
+ for (index = 0;
+ index < MAX_INDIRECT_FILES &&
+ indirect_list[index].filename != (char *)NULL;
+ index++)
+ {
+ free (indirect_list[index].filename);
+ indirect_list[index].filename = (char *)NULL;
+ }
+ return (indirect_list[0].filename = savestring (file));
+ }
+ else if (rewind)
+ {
+ index = 0;
+
+ if (indirect_list[0].filename == (char *)NULL)
+ indirect_list[0].filename = savestring (last_loaded_info_file);
+ }
+ else
+ index++;
+
+ if (index < MAX_INDIRECT_FILES &&
+ indirect_list[index].filename != (char *)NULL)
+ return (indirect_list[index].filename);
+
+ index = -1;
+ return (NULL);
+}
+
+/* **************************************************************** */
+/* */
+/* Getting Nodes */
+/* */
+/* **************************************************************** */
+
+/* A node name looks like:
+ Node: nodename with spaces but not a comma,
+or Node: (filename-containing-node)node-within-file
+or Node: (filename)
+
+ The latter case implies a nodename of "Top". All files are
+ supposed to have one.
+
+ Lastly, the nodename specified could be "*", which specifies the
+ entire file. */
+
+/* Return the directory portion of FILENAME, i.e., everything before the
+ last slash. */
+static char *
+file_directory (filename)
+ char *filename;
+{
+ register char *scan;
+ register int length;
+ char *result;
+
+ scan = filename;
+
+ while (*scan++ != '\0');
+
+ while (1)
+ {
+ if (scan == filename)
+ break;
+
+ if ((*--scan) == '/')
+ {
+ scan++;
+ break;
+ }
+ }
+
+ length = scan - filename;
+ result = (char *) xmalloc (length + 1);
+ strncpy (result, filename, length);
+ result[length] = '\0';
+
+ return (result);
+}
+
+/* Given FILENAME and DIRECTORY return a newly allocated string which
+ is either the two concatenated, or simply FILENAME if it is absolute
+ already. */
+static char *
+file_absolutize (filename, directory)
+ char *filename, *directory;
+{
+ register int filename_len, directory_len;
+ char *result;
+
+ if (filename[0] == '/')
+ return (savestring (filename));
+
+ filename_len = strlen (filename);
+ directory_len = strlen (directory);
+ result = (char *) xmalloc (directory_len + filename_len + 1);
+
+ strcpy (result, directory);
+ strcat (result, filename);
+
+ return (result);
+}
+
+/* Load FILENAME. If REMEMBER_NAME is non-zero, then remember the
+ loaded filename in CURRENT_INFO_FILE. In either case, remember
+ the name of this file in LAST_LOADED_INFO_FILE. */
+int
+get_info_file (filename, remember_name)
+ char *filename;
+ int remember_name;
+{
+ FILE *input_stream;
+ struct stat file_info;
+ int pointer, result;
+ char tempname[FILENAME_LEN];
+
+ /* Get real filename. */
+ strcpy (tempname, opsys_filename (filename));
+
+ /* If the file doesn't exist, try again with the name in lower case. */
+ result = stat (tempname, &file_info);
+
+ if (result < 0)
+ {
+ register int i;
+ char *lowered_name;
+
+ lowered_name = (char *)xmalloc (1 + strlen (filename));
+
+ for (i = 0; lowered_name[i] = to_lower (filename[i]); i++)
+ ;
+
+ strcpy (tempname, opsys_filename (lowered_name));
+ result = stat (tempname, &file_info);
+ }
+
+ /* See if this file is the last loaded one. */
+ if (!result && (strcmp (last_loaded_info_file, tempname) == 0))
+ return (1);
+
+ /* Now try to open the file. */
+ if (result || (input_stream = fopen (tempname, "r")) == NULL)
+ {
+ file_error (tempname);
+ return (0);
+ }
+
+ /* If we already have a file loaded, then free it first. */
+ if (info_file)
+ {
+ free (info_file);
+
+ if (!indirect)
+ {
+ /* Then the tag table is also no longer valid. */
+ tag_table = (char *) NULL;
+ }
+ }
+
+ /* Read the contents of the file into a new buffer. */
+
+ info_file = (char *) xmalloc (info_buffer_len = file_info.st_size);
+ fread (info_file, 1, info_buffer_len, input_stream);
+ fclose (input_stream);
+ strcpy (last_loaded_info_file, tempname);
+ if (remember_name)
+ {
+ strcpy (current_info_file, tempname);
+ if (indirect)
+ {
+ int idx;
+ indirect = 0;
+ free (tag_table);
+ }
+ }
+ else
+ return (1);
+
+ /* Force redisplay, since we are looking at a new file. */
+ window_bashed = 1;
+
+ /* The file has been read, and we don't know anything about it.
+ Find out if it contains a tag table. */
+
+ tag_table = NULL; /* assume none. */
+ indirect = 0;
+ tag_buffer_len = 0;
+
+ set_search_constraints (info_file, info_buffer_len);
+
+ /* Go to the last few lines in the file. */
+ pointer = back_lines (8, info_buffer_len);
+ pointer = search_forward (TAG_TABLE_END_STRING, pointer);
+
+ if (pointer > -1)
+ {
+ /* Then there is a tag table. Find the start of it,
+ and remember that. */
+ pointer = search_backward (TAG_TABLE_BEG_STRING, pointer);
+
+ /* Handle error for malformed info file. */
+ if (pointer < 0)
+ display_error ("Start of tag table not found!");
+ else
+ {
+ /* No problem. If this file is an indirect file, then the contents
+ of the tag table must remain in RAM the entire time. Otherwise,
+ we can flush the tag table with the file when the file is flushed.
+ So, if indirect, remember that, and copy the table to another
+ place.*/
+
+ int indirect_check = forward_lines (2, pointer);
+
+ tag_table = info_file + pointer;
+ tag_buffer_len = info_buffer_len - pointer;
+
+ /* Shorten the search constraints. */
+ info_buffer_len = pointer;
+
+ if (looking_at ("(Indirect)\n", indirect_check))
+ {
+ /* We have to find the start of the indirect file's
+ information. */
+ tag_table = (char *) xmalloc (tag_buffer_len);
+
+ bcopy (&info_file[indirect_check], tag_table, tag_buffer_len);
+
+ /* Find the list of filenames. */
+ indirect_top = search_backward ("Indirect:\n", indirect_check);
+ if (indirect_top < 0)
+ {
+ free (tag_table);
+ tag_table = (char *) NULL;
+ display_error ("Start of INDIRECT tag table not found!");
+ return (0);
+ }
+
+ /* Remember the filenames, and their byte offsets. */
+ {
+ /* Index into the filename/offsets array. */
+ int idx, temp_first_byte;
+ char temp_filename[FILENAME_LEN];
+ char *directory = file_directory (tempname);
+
+ info_buffer_len = indirect_top;
+
+ /* For each line, scan the info into globals. Then save
+ the information in the INDIRECT_INFO structure. */
+
+ for (idx = 0; idx < MAX_INDIRECT_FILES &&
+ indirect_list[idx].filename != (char *) NULL;
+ idx++)
+ {
+ free (indirect_list[idx].filename);
+ indirect_list[idx].filename = (char *) NULL;
+ }
+
+ for (idx = 0;info_file[indirect_top] != info_separator_char &&
+ idx < MAX_INDIRECT_FILES;)
+ {
+ indirect_top = forward_lines (1, indirect_top);
+ if (info_file[indirect_top] == info_separator_char)
+ break;
+
+ /* Ignore blank lines. */
+ if (info_file[indirect_top] == '\n')
+ continue;
+
+ sscanf (&info_file[indirect_top], "%s%d",
+ temp_filename, &temp_first_byte);
+
+ if (strlen (temp_filename))
+ {
+ temp_filename[strlen (temp_filename) - 1] = '\0';
+ indirect_list[idx].filename =
+ file_absolutize (temp_filename, directory);
+ indirect_list[idx].first_byte = temp_first_byte;
+ idx++;
+ }
+ }
+
+ free (directory);
+
+ /* Terminate the table. */
+ if (idx == MAX_INDIRECT_FILES)
+ {
+ display_error
+ ("Sorry, the INDIRECT file array isn't large enough.");
+ idx--;
+ }
+ indirect_list[idx].filename = (char *) NULL;
+ }
+ indirect = 1;
+ } else {
+ ;
+ }
+ }
+ }
+ return (1);
+}
+
+/* Make current_info_node be NODENAME. This could involve loading
+ a file, etc. POPPING is non-zero if we got here because we are
+ popping one level. */
+int
+get_node (filename, nodename, popping)
+ char *nodename, *filename;
+ int popping;
+{
+ int pointer;
+ char internal_filename[FILENAME_LEN];
+ char internal_nodename[NODENAME_LEN];
+
+ if (nodename && *nodename)
+ {
+ /* Maybe nodename looks like: (filename)nodename, or worse: (filename).
+ If so, extract the stuff out. */
+ if (*nodename == '(')
+ {
+ int temp = 1, temp1 = 0;
+ char character;
+
+ filename = internal_filename;
+
+ while ((character = nodename[temp]) && character != ')')
+ {
+ filename[temp - 1] = character;
+ temp++;
+ }
+ filename[temp - 1] = '\0';
+ temp++; /* skip the closing ')' */
+
+ /* We have the filename now. The nodename follows. */
+ internal_nodename[0] = '\0';
+
+ while (nodename[temp] == ' ' ||
+ nodename[temp] == '\t' ||
+ nodename[temp] == '\n')
+ temp++;
+
+ if (nodename[temp])
+ while (internal_nodename[temp1++] = nodename[temp++])
+ ;
+ else if (*filename != '\0')
+ strcpy (internal_nodename,"Top");
+
+ nodename = internal_nodename;
+ }
+ }
+
+ if (!popping)
+ push_node (current_info_file, current_info_node, pagetop, nodetop);
+
+ if (!nodename || !*nodename)
+ {
+ nodename = internal_nodename;
+ strcpy (nodename, "Top");
+ }
+
+ if (!filename || !*filename)
+ {
+ filename = internal_filename;
+ strcpy (filename, current_info_file);
+ }
+
+ if (!*filename)
+ strcpy (filename, "DIR");
+
+ if (!get_info_file (filename, 1))
+ goto node_not_found;
+
+ if (strcmp (nodename, "*") == 0)
+ {
+ /* The "node" that we want is the entire file. */
+ pointer = 0;
+ goto found_node;
+ }
+
+ /* If we are using a tag table, see if we can find the nodename in it. */
+ if (tag_table)
+ {
+ pointer = find_node_in_tag_table (nodename, 0);
+ if (pointer < 1)
+ {
+ int pop_node ();
+
+ /* The search through the tag table failed. Maybe we
+ should try searching the buffer? Nahh, just barf. */
+ node_not_found:
+ if (popping)
+ return (0); /* Second time through. */
+
+ {
+ int save_inhibit = totally_inhibit_errors;
+
+ totally_inhibit_errors = 0;
+ display_error
+ ("Sorry, unable to find the node \"%s\" in the file \"%s\".",
+ nodename, filename);
+ totally_inhibit_errors = save_inhibit;
+ }
+
+ current_info_file[0] = '\0';
+ current_info_node[0] = '\0';
+ last_loaded_info_file[0] = '\0';
+ pop_node (internal_filename, internal_nodename, &nodetop, &pagetop);
+ get_node (internal_filename, internal_nodename, 1);
+ return (0);
+ }
+
+ /* Otherwise, the desired location is right here.
+ Scarf the position byte. */
+ while (tag_table[pointer] != '\177')
+ pointer++;
+
+ sscanf (&tag_table[pointer + 1], "%d", &pointer);
+
+ /* Okay, we have a position pointer. If this is an indirect file,
+ then we should look through the indirect_list for the first
+ element.first_byte which is larger than this. Then we can load
+ the specified file, and win. */
+ if (indirect)
+ {
+ /* Find the filename for this node. */
+ int idx;
+ for (idx = 0; idx < MAX_INDIRECT_FILES &&
+ indirect_list[idx].filename != (char *) NULL; idx++)
+ {
+ if (indirect_list[idx].first_byte > pointer)
+ {
+ /* We found it. */
+ break;
+ }
+ }
+ if (!get_info_file (indirect_list[idx - 1].filename, 1))
+ goto node_not_found;
+ pointer -= indirect_list[idx - 1].first_byte;
+
+ /* Here is code to compensate for the header of an indirect file. */
+ {
+ int tt = find_node_start (0);
+ if (tt > -1)
+ pointer += tt;
+ }
+ }
+ else
+ {
+ /* This tag table is *not* indirect. The filename of the file
+ containing this node is the same as the current file. The
+ line probably looks like:
+ File: info, Node: Checking25796 */
+ }
+ }
+ else
+ {
+#if defined (NOTDEF)
+ /* We don't have a tag table. The node can only be found by
+ searching this file in its entirety. */
+ if (!get_info_file (filename, 1))
+ return (0);
+#endif /* NOTDEF */
+ pointer = 0;
+ }
+
+ /* Search this file, using pointer as a good guess where to start. */
+ /* This is the same number that RMS used. It might be right or wrong. */
+ pointer -= 1000;
+ if (pointer < 0)
+ pointer = 0;
+
+ pointer = find_node_in_file (nodename, pointer);
+ if (pointer < 0)
+ goto node_not_found;
+
+ /* We found the node in its file. Remember exciting information. */
+
+found_node:
+ back_lines (0, pointer);
+ nodetop = pagetop = pointer;
+ strcpy (current_info_node, nodename);
+ strcpy (current_info_file, filename);
+ get_node_extent ();
+ return (1);
+}
+
+/* Get the bounds for this node. NODETOP points to the start of the
+ node. Scan forward looking for info_separator_char, and remember
+ that in NODEBOT. */
+get_node_extent ()
+{
+ int idx = nodetop;
+ int character;
+ int do_it_till_end = (strcmp (current_info_node, "*") == 0);
+
+ nodelines = 0;
+
+again:
+ while ((idx < info_buffer_len) &&
+ ((character = info_file[idx]) != info_separator_char))
+ {
+ if (character == '\n')
+ nodelines++;
+ idx++;
+ }
+ if (do_it_till_end && idx != info_buffer_len)
+ {
+ idx++;
+ goto again;
+ }
+ nodebot = idx;
+}
+
+/* Locate the start of a node in the current search_buffer. Return
+ the offset to the node start, or minus one. START is the place in
+ the file at where to begin the search. */
+find_node_start (start)
+ int start;
+{
+ return (search_forward (start_of_node_string, start));
+}
+
+/* Find NODENAME in TAG_TABLE. */
+find_node_in_tag_table (nodename, offset)
+ char *nodename;
+ int offset;
+{
+ int temp;
+
+ set_search_constraints (tag_table, tag_buffer_len);
+
+ temp = offset;
+ while (1)
+ {
+ offset = search_forward (NODE_ID, temp);
+
+ if (offset < 0)
+ return (offset);
+
+ temp = skip_whitespace (offset + strlen (NODE_ID));
+
+ if (strnicmp (tag_table + temp, nodename, strlen (nodename)) == 0)
+ if (*(tag_table + temp + strlen (nodename)) == '\177')
+ return (temp);
+ }
+}
+
+/* Find NODENAME in INFO_FILE. */
+find_node_in_file (nodename, offset)
+ char *nodename;
+ int offset;
+{
+ int temp, last_offset = -1;
+
+ set_search_constraints (info_file, info_buffer_len);
+
+ while (1)
+ {
+ offset = find_node_start (offset);
+
+ if (offset == last_offset)
+ offset = -1;
+ else
+ last_offset = offset;
+
+ if (offset < 0)
+ return (offset);
+ else
+ temp = forward_lines (1, offset);
+
+ if (temp == offset)
+ return (-1); /* At last line now, just a node start. */
+ else
+ offset = temp;
+
+ temp = string_in_line (NODE_ID, offset);
+
+ if (temp > -1)
+ {
+ temp = skip_whitespace (temp + strlen (NODE_ID));
+ if (strnicmp (info_file + temp, nodename, strlen (nodename)) == 0)
+ {
+ int check_exact = *(info_file + temp + strlen (nodename));
+
+ if (check_exact == '\t' ||
+ check_exact == ',' ||
+ check_exact == '.' ||
+ check_exact == '\n')
+ return (offset);
+ }
+ }
+ }
+}
+
+
+/* **************************************************************** */
+/* */
+/* Dumping and Printing Nodes */
+/* */
+/* **************************************************************** */
+
+/* Make a temporary filename based on STARTER and the PID of this Info. */
+char *
+make_temp_filename (starter)
+ char *starter;
+{
+ register int i;
+ char *temp;
+
+ temp = (char *) xmalloc (strlen (starter) + 10);
+ sprintf (temp, "%s-%d", starter, getpid ());
+
+ for (i = 0; temp[i]; i++)
+ if (!isalnum (temp[i]))
+ temp[i] = '-';
+
+ return (temp);
+}
+
+/* Delete a file. Print errors if necessary. */
+deletefile (filename)
+ char *filename;
+{
+ if (unlink (filename) != 0)
+ {
+ file_error (filename);
+ return (1);
+ }
+ return (0);
+}
+
+printfile (filename)
+ char *filename;
+{
+ int length = strlen (print_command) + strlen (filename) + strlen ("\n") + 1;
+ char *command = (char *) xmalloc (length);
+ int error;
+
+ display_error ("Printing file `%s'...\n", filename);
+ sprintf (command, "%s %s", print_command, filename);
+ error = system (command);
+ if (error)
+ display_error ("Can't invoke `%s'", command);
+ free (command);
+ return (error);
+}
+
+/* Dump the current node into a file named FILENAME.
+ Return 0 if the dump was successful, otherwise,
+ print error and exit. */
+dump_current_node (filename)
+ char *filename;
+{
+ int c, i = nodetop;
+ FILE *output_stream;
+
+ if (strcmp (filename, "-") == 0)
+ output_stream = stdout;
+ else
+ output_stream = fopen (filename, "w");
+
+ if (output_stream == (FILE *) NULL)
+ {
+ file_error (filename);
+ return (1);
+ }
+
+ while (i < nodebot && i < info_buffer_len)
+ {
+ c = info_file[i];
+ if (CTRL_P (c) && !(index ("\n\t\f", c)))
+ {
+ putc ('^', output_stream);
+ c = UNCTRL (c);
+ }
+
+ if (putc (c, output_stream) == EOF)
+ {
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+ file_error (filename);
+ return (1);
+ }
+ i++;
+ }
+
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Toplevel eval loop. */
+/* */
+/* **************************************************************** */
+
+#define MENU_HEADER "\n* Menu:"
+#define MENU_ID "\n* "
+#define FOOTNOTE_HEADER "*Note"
+
+/* Number of items that the current menu has. */
+int the_menu_size = 0;
+
+/* The node that last made a menus completion list. */
+char menus_nodename[NODENAME_LEN];
+char menus_filename[NODENAME_LEN];
+
+static int search_start = 0;
+
+/* The default prompt string for the Follow Reference command. */
+char *visible_footnote = (char *)NULL;
+toploop ()
+{
+ int done, inhibit_display;
+ int command, last_command;
+ int last_pointer, count, new_ypos, last_pagetop;
+ char nodename[NODENAME_LEN];
+
+ done = inhibit_display = 0;
+ command = last_command = 0;
+ new_ypos = last_pagetop = -1;
+
+ while (!done)
+ {
+ if (!inhibit_display &&
+ (window_bashed || (pagetop != last_pagetop)))
+ display_page ();
+
+ inhibit_display = window_bashed = 0;
+ last_pagetop = pagetop;
+
+ nodename[0] = '\0'; /* Don't display old text in input line. */
+
+ last_command = command;
+
+ if (last_command == 'S')
+ cursor_to (search_start);
+ else
+ goto_xy (echo_area.left, echo_area.top);
+
+ command = blink_cursor ();
+ clear_echo_area ();
+
+ if (command == EOF)
+ {
+ done = 1;
+ continue;
+ }
+ command = to_upper (command);
+
+ switch (command)
+ {
+ case 'D':
+ get_node ((char *) NULL, "(dir)Top", 0);
+ break;
+
+ case 'H':
+ if ((the_window.bottom - the_window.top) < 24)
+ get_node ((char *) NULL, "(info)Help-Small-Screen", 0);
+ else
+ get_node ((char *) NULL, "(info)Help", 0);
+ break;
+
+ case 'N':
+ if (!next_node ())
+ {
+ display_error ("No NEXT for this node!");
+ inhibit_display = 1;
+ }
+ break;
+
+ case 'P':
+ if (!prev_node ())
+ {
+ display_error ("No PREV for this node!");
+ inhibit_display = 1;
+ }
+ break;
+
+ case 'U':
+ {
+ int savetop = pagetop;
+
+ if (!up_node ())
+ {
+ display_error ("No UP for this node!");
+ inhibit_display = 1;
+ pagetop = savetop;
+ }
+ break;
+ }
+
+ case 'M':
+ if (!build_menu ())
+ {
+ display_error ("No menu in this node!");
+ inhibit_display = 1;
+ break;
+ }
+
+ if (!readline ("Menu item: ", nodename, NODENAME_LEN, 1))
+ {
+ clear_echo_area ();
+ inhibit_display = 1;
+ break;
+ }
+
+ I_goto_xy (echo_area.left, echo_area.top);
+ if (!find_menu_node (nodename, nodename))
+ {
+ display_error ("\"%s\" is not a menu item!", nodename);
+ inhibit_display = 1;
+ break;
+ }
+
+ if (get_node ((char *) NULL, nodename, 0))
+ clear_echo_area ();
+ break;
+
+ case 'F':
+ {
+ char footnote[NODENAME_LEN];
+
+ if (!build_notes ())
+ {
+ display_error ("No cross-references in this node!");
+ inhibit_display = 1;
+ break;
+ }
+
+ strcpy (footnote, visible_footnote);
+ if (!readline ("Follow reference: ", footnote, NODENAME_LEN, 1))
+ {
+ inhibit_display = 1;
+ break;
+ }
+
+ I_goto_xy (echo_area.left, echo_area.top);
+ if (!find_note_node (footnote, nodename))
+ {
+ display_error ("\"%s\" is not a cross-reference in this node!",
+ footnote);
+ inhibit_display = 1;
+ break;
+ }
+
+ if (get_node ((char *)NULL, nodename, 0))
+ clear_echo_area ();
+ break;
+ }
+
+ case 'L':
+ {
+ char filename[FILENAME_LEN], nodename[NODENAME_LEN];
+ int ptop, ntop;
+ if (pop_node (filename, nodename, &ntop, &ptop) &&
+ get_node (filename, nodename, 1))
+ {
+ pagetop = ptop;
+ }
+ else
+ inhibit_display = 1;
+ break;
+ }
+
+ case SPACE:
+ case CTRL ('V'):
+ if (!next_page ())
+ {
+ display_error ("At last page of this node now!");
+ inhibit_display = 1;
+ }
+ break;
+
+ case META ('V'):
+ case DELETE:
+ if (!prev_page ())
+ {
+ display_error ("At first page of this node now!");
+ inhibit_display = 1;
+ }
+ break;
+
+ case 'B':
+ if (pagetop == nodetop)
+ {
+ display_error ("Already at beginning of this node!");
+ inhibit_display = 1;
+ }
+ else
+ pagetop = nodetop;
+ break;
+
+ /* I don't want to do this this way, but the documentation
+ clearly states that '6' doesn't work. It states this for a
+ reason, and ours is not to wonder why... */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ {
+ int item = command - '0';
+
+ if (!build_menu ())
+ {
+ display_error ("No menu in this node!");
+ inhibit_display = 1;
+ break;
+ }
+
+ if (item > the_menu_size)
+ {
+ display_error ("There are only %d items in the menu!",
+ the_menu_size);
+ inhibit_display = 1;
+ break;
+ }
+
+ if (!get_menu (item))
+ inhibit_display = 1;
+ }
+ break;
+
+ case 'G':
+ if (!readline ("Goto node: ", nodename, NODENAME_LEN, 0))
+ {
+ inhibit_display = 1;
+ break;
+ }
+
+ if (get_node ((char *) NULL, nodename, 0))
+ clear_echo_area ();
+ break;
+
+ /* Search from the starting position forward for a string.
+ Select the node containing the desired string. Put the
+ top of the page screen_lines / 2 lines behind it, but not
+ before nodetop. */
+ case 'S':
+ {
+ int pointer, temp;
+ char prompt[21 + NODENAME_LEN + 1];
+ static char search_string[NODENAME_LEN] = "";
+ static char *starting_filename = NULL,
+ *starting_nodename = NULL;
+ static int starting_pagetop = 0;
+ static int wrap_search = 0;
+
+ sprintf (prompt, "Search for string [%s]: ", search_string);
+
+ if (!readline (prompt , nodename, NODENAME_LEN, 0))
+ {
+ inhibit_display = 1;
+ break;
+ }
+
+ /* If the user defaulted the search string, and the previous
+ command was search, then this is a continuation of the
+ previous search. */
+ if (((strcmp (nodename, search_string) == 0) ||
+ (!*nodename && *search_string)) &&
+ (last_command == 'S'))
+ {
+ search_start++;
+ }
+ else
+ {
+ /* Initialize the start of a new search. */
+ if (starting_filename)
+ free (starting_filename);
+
+ starting_filename = savestring (last_loaded_info_file);
+
+ if (starting_nodename)
+ free (starting_nodename);
+
+ starting_nodename = savestring (nodename ? nodename : "");
+
+ starting_pagetop = pagetop;
+ search_start = pagetop;
+ wrap_search = 0;
+
+ if (*nodename != '\0')
+ strcpy (search_string, nodename);
+ }
+
+ I_goto_xy (echo_area.left, echo_area.top);
+
+ {
+ static int pushed = 0; /* How many files are pushed? */
+ int found_string = 0; /* Did we find our string? */
+
+ if (wrap_search)
+ {
+ push_filestack (next_info_file ((char *)NULL, 1), 0);
+ pushed++;
+ search_start = 0;
+ }
+
+ for (;;)
+ {
+ set_search_constraints (info_file, info_buffer_len);
+ pointer = search_forward (search_string, search_start);
+
+ if (pointer != -1)
+ {
+ found_string = 1;
+ break;
+ }
+ else
+ {
+ char *next_file;
+
+ next_file = next_info_file ((char *)NULL, 0);
+
+ if (next_file != NULL)
+ {
+ if (pushed)
+ {
+ pop_filestack ();
+ pushed--;
+ }
+
+ push_filestack (next_file, 0);
+ pushed++;
+ search_start = 0;
+#if 1
+ I_goto_xy (echo_area.left, echo_area.top);
+ print_string ("Searching file %s...\n", next_file);
+#endif
+ continue;
+ }
+
+ if (wrap_search)
+ {
+ display_error
+ ("\"%s\" not found!",
+ search_string);
+
+ inhibit_display = 1;
+ wrap_search = 0;
+
+ if (pushed)
+ {
+ pop_filestack ();
+ pushed--;
+ }
+ break;
+ }
+ else
+ {
+ display_error ("Search: End of file");
+ inhibit_display = 1;
+ wrap_search = 1;
+
+ if (pushed)
+ {
+ pop_filestack ();
+ pushed--;
+ }
+ break;
+ }
+ }
+ }
+
+ if (pushed)
+ {
+ swap_filestack ();
+ pop_filestack ();
+ pushed--;
+ }
+
+ if (!found_string)
+ break;
+
+ wrap_search = 0;
+ temp = search_backward (start_of_node_string, pointer);
+
+ if (temp != -1)
+ {
+ search_start = pointer;
+ pointer = forward_lines (1, temp);
+ }
+
+ if (temp == -1 || !extract_field ("Node:", nodename, pointer))
+ {
+ display_error
+ ("There doesn't appear to be a nodename for this node.");
+ get_node ((char *)NULL, "*", 0);
+ pagetop = pointer;
+ break;
+ }
+
+ /* Get the node if it is different than the one already
+ loaded. */
+ if (strcmp (nodename, starting_nodename) != 0)
+ {
+ free (starting_nodename);
+ starting_nodename = savestring (nodename);
+
+ if (get_node ((char *) NULL, nodename, 0))
+ clear_echo_area ();
+ }
+
+ /* Reset the top of page if necessary. */
+ {
+ if ((strcmp (last_loaded_info_file, starting_filename) != 0) ||
+ (starting_pagetop != pagetop) ||
+ (search_start > pagebot))
+ {
+ pointer =
+ back_lines ((the_window.bottom - the_window.top) / 2,
+ forward_lines (1, search_start));
+
+ if (pointer < nodetop)
+ pointer = nodetop;
+
+ pagetop = pointer;
+ window_bashed = 1;
+ }
+ else
+ inhibit_display = 1;
+ }
+ break;
+ }
+ }
+
+ case CTRL ('H'):
+ case '?':
+ help_use_info ();
+ last_pagetop = -1;
+ break;
+
+ case 'Q':
+ done = 1;
+ break;
+
+ case CTRL ('L'): /* Control-l is redisplay. */
+ window_bashed = 1;
+ if (last_command == 'S')
+ command = 'S';
+ break;
+
+ case '(': /* You *must* be trying to type a complete nodename. */
+ strcpy (nodename, "(");
+ if (!readline ("Goto node: ", nodename, NODENAME_LEN, 0))
+ {
+ inhibit_display = 1;
+ clear_echo_area ();
+ break;
+ }
+ I_goto_xy (echo_area.left, echo_area.top);
+ if (get_node ((char *) NULL, nodename, 0))
+ clear_echo_area ();
+ break;
+
+ case CTRL ('P'):
+ /* Print the contents of this node on the default printer. We
+ would like to let the user specify the printer, but we don't
+ want to ask her each time which printer to use. Besides, he
+ might not know, which is why it (the user) is in the need of
+ Info. */
+ {
+ char *tempname = make_temp_filename (current_info_node);
+ if (dump_current_node (tempname) == 0 &&
+ printfile (tempname) == 0 &&
+ deletefile (tempname) == 0)
+ {
+ display_error ("Printed node. Go pick up your output.\n");
+ }
+ inhibit_display = 1;
+ free (tempname);
+ }
+ break;
+
+ default:
+ inhibit_display = 1;
+ display_error ("Unknown command! Press '?' for help.");
+
+ }
+ }
+}
+
+/* Return the screen column width that the line from START to END
+ requires to display. */
+line_length (start, end)
+ int start, end;
+{
+ int count = 0;
+
+ while (start < end)
+ {
+ if (info_file[start] == '\t')
+ count += 7 - (count % 8);
+ else if (CTRL_P (info_file[start]))
+ count += 2;
+ else
+ count++;
+
+ start++;
+ }
+
+ return (count);
+}
+
+/* Tell this person how to use Info. */
+help_use_info ()
+{
+ open_typeout ();
+ clear_screen ();
+ print_string ("\n\
+ Commands in Info\n\
+\n\
+h Invoke the Info tutorial.\n\
+\n\
+Selecting other nodes:\n\
+n Move to the \"next\" node of this node.\n\
+p Move to the \"previous\" node of this node.\n\
+u Move \"up\" from this node.\n\
+m Pick menu item specified by name.\n\
+ Picking a menu item causes another node to be selected.\n\
+f Follow a cross reference. Reads name of reference.\n\
+l Move to the last node you were at.\n\
+d Move to the `directory' node. Equivalent to `gDIR'.\n\
+\n\
+Moving within a node:\n\
+Space Scroll forward a page.\n\
+DEL Scroll backward a page.\n\
+b Go to the beginning of this node.\n\
+\n\
+Advanced commands:\n\
+q Quit Info.\n\
+1 Pick first item in node's menu.\n\
+2 - 5 Pick second ... fifth item in node's menu.\n\
+g Move to node specified by name.\n\
+ You may include a filename as well, as (FILENAME)NODENAME.\n\
+s Search through this Info file for a specified string,\n\
+ and select the node in which the next occurrence is found.\n\
+Ctl-p Print the contents of this node using `%s'.\n\
+\n\
+Done.\n\n",print_command);
+ close_typeout ();
+}
+
+/* Move to the node specified in the NEXT field. */
+int
+next_node ()
+{
+ char nodename[NODENAME_LEN];
+
+ if (!extract_field ("Next:", nodename, nodetop))
+ return (0);
+ return (get_node ((char *) NULL, nodename, 0));
+}
+
+/* Move to the node specified in the PREVIOUS field. */
+int
+prev_node ()
+{
+ char nodename[NODENAME_LEN];
+
+ if (!extract_field ("Previous:", nodename, nodetop)
+ && !extract_field ("Prev:", nodename, nodetop))
+ return (0);
+ return (get_node ((char *) NULL, nodename, 0));
+}
+
+/* Move to the node specified in the UP field. */
+int
+up_node ()
+{
+ char nodename[NODENAME_LEN];
+
+ if (!extract_field ("Up:", nodename, nodetop))
+ return (0);
+ return (get_node ((char *) NULL, nodename, 0));
+}
+
+/* Build a completion list of menuname/nodename for each
+ line in this node that is a menu item. */
+int
+build_menu ()
+{
+ int pointer = nodetop;
+ char menuname[NODENAME_LEN];
+ char nodename[NODENAME_LEN];
+
+ if (strcmp (menus_nodename, current_info_node) == 0 &&
+ strcmp (menus_filename, current_info_file) == 0)
+ return (the_menu_size != 0);
+
+ strcpy (menus_nodename, current_info_node);
+ strcpy (menus_filename, current_info_file);
+ free_completion_list ();
+ the_menu_size = 0;
+
+ set_search_constraints (info_file, nodebot);
+ if ((pointer = search_forward (MENU_HEADER, nodetop)) < 0)
+ return (0);
+
+ /* There is a menu here. Look for members of it. */
+ pointer += strlen (MENU_HEADER);
+
+ while (1)
+ {
+ int idx;
+
+ pointer = search_forward (MENU_ID, pointer);
+ if (pointer < 0)
+ break; /* No more menus in this node. */
+
+ pointer = (skip_whitespace (pointer + strlen (MENU_ID)));
+
+ idx = 0;
+ while ((menuname[idx] = info_file[pointer]) && menuname[idx] != ':')
+ idx++, pointer++;
+
+ menuname[idx] = '\0';
+ pointer++;
+
+ if (info_file[pointer] == ':')
+ {
+ strcpy (nodename, menuname);
+ }
+ else
+ {
+ int in_parens;
+
+ pointer = skip_whitespace (pointer);
+ idx = in_parens = 0;
+
+ while ((nodename[idx] = info_file[pointer]) &&
+ (in_parens ||
+ (nodename[idx] != '\t' &&
+ nodename[idx] != '.' &&
+ nodename[idx] != ',')))
+ {
+ if (nodename[idx] == '(')
+ in_parens++;
+ else if (nodename[idx] == ')')
+ in_parens--;
+
+ idx++, pointer++;
+ }
+ nodename[idx] = '\0';
+ }
+ add_completion (menuname, nodename);
+ the_menu_size++;
+ }
+ if (the_menu_size)
+ completion_list = reverse_list (completion_list);
+ return (the_menu_size != 0);
+}
+
+/* Select ITEMth item from a list built by build_menu (). */
+int
+get_menu (item)
+ int item;
+{
+ if (!build_menu ())
+ return (0);
+
+ if (item > the_menu_size)
+ return (0);
+ else
+ {
+ COMP_ENTRY *temp = completion_list;
+
+ while (--item && temp)
+ temp = temp->next;
+
+ return (get_node ((char *) NULL, temp->data, 0));
+ }
+}
+
+/* Scan through the ?already? built menu list looking
+ for STRING. If you find it, put the corresponding nodes
+ name in NODENAME. */
+int
+find_menu_node (string, nodename)
+ char *string, *nodename;
+{
+ return (scan_list (string, nodename));
+}
+
+/* The work part of find_menu_node and find_note_node. */
+int
+scan_list (string, nodename)
+ char *string, *nodename;
+{
+ COMP_ENTRY *temp = completion_list;
+
+ while (temp)
+ {
+ if (stricmp (string, temp->identifier, strlen (string)) == 0)
+ {
+ strcpy (nodename, temp->data);
+ return (1);
+ }
+ temp = temp->next;
+ }
+ return (0);
+}
+
+/* Remove <CR> and whitespace from string, replacing them with
+ only one space. Exception: <CR> at end of string disappears. */
+clean_up (string)
+ char *string;
+{
+ char *to;
+
+ /* Skip all whitespace characters found at the start of STRING. */
+ while (whitespace (*string))
+ string++;
+
+ to = string;
+
+ while (*to = *string++)
+ {
+ if (*to == '\n' || *to == ' ')
+ {
+ *to = ' ';
+
+ while (*string == ' ' || *string == '\t')
+ string++;
+ }
+ to++;
+ }
+}
+
+/* Find a reference to "*Note". Return the offset of the start
+ of that reference, or -1. */
+find_footnote_ref (from)
+ int from;
+{
+ while (1)
+ {
+ from = search_forward (FOOTNOTE_HEADER, from);
+ if (from < 0)
+ return (from);
+ else
+ from += strlen (FOOTNOTE_HEADER);
+ if (info_file[from] == ' ' ||
+ info_file[from] == '\n' ||
+ info_file[from] == '\t')
+ return (from);
+ }
+}
+
+/* Build an array of (footnote.nodename) for each footnote in this node. */
+int
+build_notes ()
+{
+ int pointer;
+ char notename[NODENAME_LEN];
+ char nodename[NODENAME_LEN];
+
+ set_search_constraints (info_file, nodebot);
+
+ if ((find_footnote_ref (nodetop)) < 0)
+ return (0);
+ pointer = nodetop;
+
+ menus_filename[0] = menus_nodename[0] = '\0';
+ visible_footnote = "";
+ free_completion_list ();
+
+ while (1)
+ {
+ int idx;
+
+ pointer = find_footnote_ref (pointer);
+ if (pointer < 0)
+ break; /* no more footnotes in this node. */
+
+ pointer = skip_whitespace_and_cr (pointer);
+ idx = 0;
+
+ while ((notename[idx] = info_file[pointer]) && notename[idx] != ':')
+ {
+ idx++, pointer++;
+ }
+
+ notename[idx] = '\0';
+ clean_up (notename);
+ pointer++;
+ if (info_file[pointer] == ':')
+ {
+ strcpy (nodename, notename);
+ }
+ else
+ {
+ int in_parens = 0;
+
+ pointer = skip_whitespace (pointer);
+ idx = 0;
+
+ while ((nodename[idx] = info_file[pointer]) &&
+ (in_parens ||
+ (nodename[idx] != '\t' &&
+ nodename[idx] != '.' &&
+ nodename[idx] != ',')))
+ {
+ if (nodename[idx] == '(')
+ in_parens++;
+ else if (nodename[idx] == ')')
+ in_parens--;
+
+ idx++, pointer++;
+ }
+ nodename[idx] = '\0';
+ clean_up (nodename);
+ }
+ /* Add the notename/nodename to the list. */
+ add_completion (notename, nodename);
+ the_menu_size++;
+
+ /* Remember this identifier as the default if it is the first one in the
+ page. */
+ if (!(*visible_footnote) &&
+ pointer > pagetop &&
+ pointer < forward_lines (the_window.bottom - the_window.top, pointer))
+ visible_footnote = completion_list->identifier;
+ }
+ if (the_menu_size)
+ completion_list = reverse_list (completion_list);
+ return (the_menu_size != 0);
+}
+
+/* Scan through the ?already? built footnote list looking for STRING.
+ If found, place the corresponding node name in NODENAME. */
+int
+find_note_node (string, nodename)
+ char *string, *nodename;
+{
+ return (scan_list (string, nodename));
+}
+
+/* **************************************************************** */
+/* */
+/* Page Display */
+/* */
+/* **************************************************************** */
+
+
+/* The display functions for GNU Info. */
+int display_ch, display_cv;
+int display_point;
+
+/* Display the current page from pagetop down to the bottom of the
+ page or the bottom of the node, whichever comes first. */
+display_page ()
+{
+ display_point = pagetop;
+ display_ch = the_window.left;
+ display_cv = the_window.top;
+ generic_page_display ();
+}
+
+/* Print the page from display_point to bottom of node, or window,
+ whichever comes first. Start printing at display_ch, display_cv. */
+generic_page_display ()
+{
+ int done_with_display = 0;
+ int character;
+
+ goto_xy (display_ch, display_cv);
+
+ while (!done_with_display)
+ {
+ if (display_point == nodebot)
+ {
+ clear_eop ();
+ goto display_finish;
+ }
+
+ character = info_file[display_point];
+
+ if ((display_width (character, the_window.ch) + the_window.ch)
+ >= the_window.right)
+ display_carefully (character);
+ else
+ charout (character);
+
+ if ((the_window.cv >= the_window.bottom)
+ || (the_window.cv == the_window.top
+ && the_window.ch == the_window.left))
+ {
+ display_finish:
+ pagebot = display_point;
+ make_modeline ();
+ done_with_display++;
+ continue;
+ }
+ else
+ display_point++;
+ }
+ fflush (stdout);
+}
+
+/* Display character carefully, ensuring that no scrolling takes
+ place, even in the case of funky control characters. */
+display_carefully (character)
+ int character;
+{
+ if (CTRL_P (character))
+ {
+ switch (character)
+ {
+ case RETURN:
+ case NEWLINE:
+ case TAB:
+ clear_eol ();
+ advance (the_window.right - the_window.ch);
+ break;
+ default:
+ charout ('^');
+ if (the_window.cv == the_window.bottom)
+ break;
+ else
+ charout (UNCTRL (character));
+ }
+ }
+ else
+ charout (character);
+}
+
+/* Move the cursor to POSITION in page. Return non-zero if successful. */
+cursor_to (position)
+ int position;
+{
+ int ch, cv, character;
+ int point;
+
+ if (position > pagebot || position < pagetop)
+ return (0);
+
+ point = pagetop;
+ ch = the_window.left;
+ cv = the_window.top;
+
+ while (point < position)
+ {
+ character = info_file[point++];
+
+ ch += display_width (character, ch);
+
+ if (ch >= the_window.right)
+ {
+ ch = ch - the_window.right;
+ cv++;
+
+ if (cv >= the_window.bottom)
+ return (0);
+ }
+ }
+ goto_xy (ch, cv);
+ return (1);
+}
+
+/* Move to the next page in this node. Return 0 if
+ we can't get to the next page. */
+int
+next_page ()
+{
+ int pointer;
+
+ pointer =
+ forward_lines ((the_window.bottom - the_window.top) - 2, pagetop);
+
+ if (pointer >= nodebot)
+ return (0);
+
+ /* Hack for screens smaller than displayed line width. */
+ if (pointer > display_point)
+ {
+ pointer = display_point;
+ back_lines (1);
+ }
+ pagetop = pointer;
+ return (1);
+}
+
+/* Move to the previous page in this node. Return zero if
+ there is no previous page. */
+int
+prev_page ()
+{
+ int pointer =
+ back_lines ((the_window.bottom - the_window.top) - 2, pagetop);
+
+ if (pagetop == nodetop)
+ return (0);
+
+ if (pointer < nodetop)
+ pointer = nodetop;
+
+ pagetop = pointer;
+ return (1);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Utility Functions */
+/* */
+/* **************************************************************** */
+
+char *search_buffer; /* area in ram to scan through. */
+int buffer_bottom; /* Length of this area. */
+
+/* Set the global variables that all of these routines use. */
+set_search_constraints (buffer, extent)
+ char *buffer;
+ int extent;
+{
+ search_buffer = buffer;
+ buffer_bottom = extent;
+}
+
+/* Move back to the start of this line. */
+to_beg_line (from)
+ int from;
+{
+ while (from && search_buffer[from - 1] != '\n')
+ from--;
+ return (from);
+}
+
+/* Move forward to the end of this line. */
+to_end_line (from)
+{
+ while (from < buffer_bottom && search_buffer[from] != '\n')
+ from++;
+ return (from);
+}
+
+/* Move back count lines in search_buffer starting at starting_pos.
+ Returns the start of that line. */
+back_lines (count, starting_pos)
+ int count, starting_pos;
+{
+ starting_pos = to_beg_line (starting_pos);
+ while (starting_pos && count)
+ {
+ starting_pos = to_beg_line (starting_pos - 1);
+ count--;
+ }
+ return (starting_pos);
+}
+
+/* Move forward count lines starting at starting_pos.
+ Returns the start of that line. */
+forward_lines (count, starting_pos)
+ int count, starting_pos;
+{
+ starting_pos = to_end_line (starting_pos);
+ while (starting_pos < buffer_bottom && count)
+ {
+ starting_pos = to_end_line (starting_pos + 1);
+ count--;
+ }
+ return (to_beg_line (starting_pos));
+}
+
+/* Search for STRING in SEARCH_BUFFER starting at STARTING_POS.
+ Return the location of the string, or -1 if not found. */
+search_forward (string, starting_pos)
+ char *string;
+ int starting_pos;
+{
+ register int c, i, len;
+ register char *buff, *end;
+ char *alternate;
+
+
+ /* We match characters in SEARCH_BUFFER against STRING and ALTERNATE.
+ ALTERNATE is a case reversed version of STRING; this is cheaper than
+ case folding each character before comparison. */
+
+ /* Build the alternate string. */
+ alternate = savestring (string);
+ len = strlen (string);
+
+ for (i = 0; i < len; i++)
+ {
+ c = alternate[i];
+
+ if (c >= 'a' && c <= 'z')
+ alternate[i] = c - 32;
+ else if (c >= 'A' && c <= 'Z')
+ alternate[i] = c + 32;
+ }
+
+ buff = search_buffer + starting_pos;
+ end = search_buffer + buffer_bottom + 1;
+
+ while (buff < end)
+ {
+ for (i = 0; i < len; i++)
+ {
+ c = buff[i];
+
+ if (c != string[i] && c != alternate[i])
+ break;
+ }
+
+ if (!string[i])
+ {
+ free (alternate);
+ return (buff - search_buffer);
+ }
+
+ buff++;
+ }
+
+ free (alternate);
+ return (-1);
+}
+
+/* Search for STRING in SEARCH_BUFFER starting at STARTING_POS.
+ Return the location of the string, or -1 if not found. */
+search_backward (string, starting_pos)
+ char *string;
+ int starting_pos;
+{
+ int len = strlen (string);
+ while (starting_pos - len > -1)
+ {
+ if (strnicmp (search_buffer + (starting_pos - len), string, len) == 0)
+ return (starting_pos - len);
+ else
+ starting_pos--;
+ }
+ return (-1);
+}
+
+/* Only search for STRING from POINTER to end of line. Return offset
+ of string, or -1 if not found. */
+string_in_line (string, pointer)
+ char *string;
+ int pointer;
+{
+ int old_buffer_bottom = buffer_bottom;
+
+ set_search_constraints (search_buffer, to_end_line (pointer));
+ pointer = search_forward (string, pointer);
+ buffer_bottom = old_buffer_bottom;
+ return (pointer);
+}
+
+/* Skip whitespace characters at OFFSET in SEARCH_BUFFER.
+ Return the next non-whitespace character or -1 if BUFFER_BOTTOM
+ is reached. */
+skip_whitespace (offset)
+ int offset;
+{
+ int character;
+
+ while (offset < buffer_bottom)
+ {
+ character = search_buffer[offset];
+ if (character == ' ' || character == '\t')
+ offset++;
+ else
+ return (offset);
+ }
+ return (-1);
+}
+
+/* Skip whitespace characters including <CR> at OFFSET in
+ SEARCH_BUFFER. Return the position of the next non-whitespace
+ character, or -1 if BUFFER_BOTTOM is reached. */
+skip_whitespace_and_cr (offset)
+ int offset;
+{
+ while (1)
+ {
+ offset = skip_whitespace (offset);
+ if (offset > 0 && search_buffer[offset] != '\n')
+ return (offset);
+ else
+ offset++;
+ }
+}
+
+/* Extract the node name part of the of the text after the FIELD.
+ Place the node name into NODENAME. Assume the line starts at
+ OFFSET in SEARCH_BUFFER. */
+int
+extract_field (field_name, nodename, offset)
+ char *field_name, *nodename;
+ int offset;
+{
+ int temp, character;
+
+ temp = string_in_line (field_name, offset);
+ if (temp < 0)
+ return (0);
+
+ temp += strlen (field_name);
+ temp = skip_whitespace (temp);
+
+ /* Okay, place the following text into NODENAME. */
+
+ while ((character = search_buffer[temp]) != ','
+ && character != '\n'
+ && character != '\t')
+ {
+ *nodename = character;
+ nodename++;
+ temp++;
+ }
+ *nodename = '\0';
+ return (1);
+}
+
+/* Return non-zero if pointer is exactly at string, else zero. */
+int
+looking_at (string, pointer)
+ char *string;
+ int pointer;
+{
+ if (strnicmp (search_buffer + pointer, string, strlen (string)) == 0)
+ return (1);
+ else
+ return (0);
+}
+
+/* File stack stuff. This is currently only used to push one file while
+ searching indirect files, but we may as well write it in full
+ generality. */
+typedef struct filestack
+{
+ struct filestack *next;
+ char filename[FILENAME_LEN];
+ char current_filename[FILENAME_LEN];
+ char *tag_table;
+ char *info_file;
+ int info_buffer_len;
+} FILESTACK;
+
+FILESTACK *filestack = NULL;
+
+int
+push_filestack (filename, remember_name)
+ char *filename;
+ int remember_name;
+{
+ FILESTACK *element = (FILESTACK *) xmalloc (sizeof (FILESTACK));
+
+ element->next = filestack;
+ filestack = element;
+
+ strcpy (filestack->filename, last_loaded_info_file);
+ strcpy (filestack->current_filename, current_info_file);
+ filestack->tag_table = tag_table;
+ filestack->info_file = info_file;
+ filestack->info_buffer_len = info_buffer_len;
+
+ *last_loaded_info_file = '\0'; /* force the file to be read */
+ info_file = (char *)NULL; /* Pretend we have no buffer. */
+ if (get_info_file (filename, remember_name))
+ {
+ return (1);
+ }
+ else
+ {
+ pop_filestack ();
+ return (0);
+ }
+}
+
+void
+pop_filestack ()
+{
+ FILESTACK *temp;
+
+ if (filestack == NULL)
+ {
+ fprintf (stderr , "File stack is empty and can't be popped\n");
+ brians_error ();
+ return;
+ }
+
+ free (info_file);
+
+ strcpy (last_loaded_info_file, filestack->filename);
+ strcpy (current_info_file, filestack->current_filename);
+ tag_table = filestack->tag_table;
+ info_file = filestack->info_file;
+ info_buffer_len = filestack->info_buffer_len;
+ set_search_constraints (info_file, info_buffer_len);
+
+ temp = filestack;
+ filestack = filestack->next;
+ free ((char *)temp);
+}
+
+/* Swap the current info file with the bottom of the filestack */
+void
+swap_filestack ()
+{
+ char t_last_loaded_info_file[FILENAME_LEN];
+ char t_current_info_file[FILENAME_LEN];
+ char *t_tag_table;
+ char *t_info_file;
+ int t_info_buffer_len;
+
+ if (filestack == NULL)
+ {
+ fprintf (stderr , "File stack is empty and can't be swapped\n");
+ brians_error ();
+ return;
+ }
+
+ strcpy (t_last_loaded_info_file, filestack->filename);
+ strcpy (t_current_info_file, filestack->current_filename);
+ t_tag_table = filestack->tag_table;
+ t_info_file = info_file;
+ t_info_buffer_len = info_buffer_len;
+
+ strcpy (filestack->filename, last_loaded_info_file);
+ strcpy (filestack->current_filename, current_info_file);
+ filestack->tag_table = tag_table;
+ filestack->info_file = info_file;
+ filestack->info_buffer_len = info_buffer_len;
+
+ strcpy (last_loaded_info_file, t_last_loaded_info_file);
+ strcpy (current_info_file, t_current_info_file);
+ tag_table = t_tag_table;
+ info_file = t_info_file;
+ info_buffer_len = t_info_buffer_len;
+}
+
+/* Now the node history stack */
+
+extern NODEINFO *Info_History;
+
+/* Save the current filename, nodename, and position on the history list.
+ We prepend. */
+int
+push_node (filename, nodename, page_position, node_position)
+ char *filename, *nodename;
+ int page_position, node_position;
+{
+ NODEINFO *newnode = (NODEINFO *) xmalloc (sizeof (NODEINFO));
+
+ newnode->next = Info_History;
+
+ newnode->filename = (char *) xmalloc (strlen (filename) + 1);
+ strcpy (newnode->filename, filename);
+
+ newnode->nodename = (char *) xmalloc (strlen (nodename) + 1);
+ strcpy (newnode->nodename, nodename);
+
+ newnode->pagetop = page_position;
+ newnode->nodetop = node_position;
+
+ Info_History = newnode;
+ return (1);
+}
+
+/* Pop one node from the node list, leaving the values in
+ passed variables. */
+int
+pop_node (filename, nodename, nodetop, pagetop)
+ char *filename, *nodename;
+ int *nodetop, *pagetop;
+{
+ if (Info_History->next == (NODEINFO *) NULL)
+ {
+ display_error ("At beginning of history now!");
+ return (0);
+ }
+ else
+ {
+ NODEINFO *releaser = Info_History;
+
+ /* If the popped file is not the current file, then force
+ the popped file to be loaded. */
+ if (strcmp (Info_History->filename, last_loaded_info_file) != 0)
+ last_loaded_info_file[0] = '\0';
+
+ strcpy (filename, Info_History->filename);
+ strcpy (nodename, Info_History->nodename);
+ *pagetop = Info_History->pagetop;
+ *nodetop = Info_History->nodetop;
+ free (Info_History->nodename);
+ free (Info_History->filename);
+ Info_History = Info_History->next;
+ free (releaser);
+ return (1);
+ }
+}
+
+/* Whoops, Unix doesn't have strnicmp. */
+
+/* Compare at most COUNT characters from string1 to string2. Case
+ doesn't matter. */
+int
+strnicmp (string1, string2, count)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ while (count)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+ if (to_upper (ch1) == to_upper (ch2))
+ count--;
+ else
+ break;
+ }
+ return (count);
+}
+
+/* Compare string1 to string2. Case doesn't matter. */
+int
+stricmp (string1, string2)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ while (1)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+
+ if (ch1 == '\0')
+ return (ch2 != '\0');
+
+ if ((ch2 == '\0') ||
+ (to_upper (ch1) != to_upper (ch2)))
+ return (1);
+ }
+}
+
+/* Make the user type "Y" or "N". */
+int
+get_y_or_n_p ()
+{
+ int character;
+ print_string (" (Y or N)?");
+ clear_eol ();
+
+until_we_like_it:
+
+ character = blink_cursor ();
+ if (character == EOF)
+ return (0);
+ if (to_upper (character) == 'Y')
+ {
+ charout (character);
+ return (1);
+ }
+
+ if (to_upper (character) == 'N')
+ {
+ charout (character);
+ return (0);
+ }
+
+ if (character == ABORT_CHAR)
+ {
+ ding ();
+ return (0);
+ }
+
+ goto until_we_like_it;
+}
+
+/* Move the cursor to the desired column in the window. */
+indent_to (screen_column)
+ int screen_column;
+{
+ int counter = screen_column - the_window.ch;
+ if (counter > 0)
+ {
+ while (counter--)
+ charout (' ');
+ }
+ else if (screen_column != 0)
+ charout (' ');
+}
+
+
+/* **************************************************************** */
+/* */
+/* Error output/handling. */
+/* */
+/* **************************************************************** */
+
+/* Display specific error from known file error table. */
+file_error (file)
+ char *file;
+{
+ extern int errno;
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+
+ if (errno < sys_nerr)
+ display_error ("%s: %s", file, sys_errlist[errno]);
+ else
+ display_error ("%s: Unknown error %d", file, errno);
+}
+
+/* Display the error in the echo-area using format_string and args.
+ This is a specialized interface to printf. */
+display_error (format_string, arg1, arg2)
+ char *format_string;
+{
+ extern int terminal_inited_p;
+ char output_buffer[1024];
+
+ if (totally_inhibit_errors)
+ return;
+
+ sprintf (output_buffer, format_string, arg1, arg2);
+ if (terminal_inited_p)
+ {
+ new_echo_area ();
+ ding ();
+ print_string ("%s", output_buffer);
+ close_echo_area ();
+ }
+ else
+ {
+ fprintf (stderr, "%s\n", output_buffer);
+ }
+}
+
+/* Tell everybody what a loser I am. If you see this error,
+ send me a bug report. */
+brians_error ()
+{
+ display_error ("You are never supposed to see this error.\n");
+ display_error ("Tell bfox@ai.mit.edu to fix this someday.\n");
+ return (-1);
+}
+
+/* **************************************************************** */
+/* */
+/* Terminal IO, and Driver */
+/* */
+/* **************************************************************** */
+
+/* The Unix termcap interface code. */
+
+#define NO_ERROR 0
+#define GENERIC_ERROR 1
+#define NO_TERMINAL_DESCRIPTOR 2
+#define OUT_OF_MEMORY 3
+#define BAD_TERMINAL 4
+
+#define FERROR(msg) fprintf (stderr, msg); exit (GENERIC_ERROR)
+
+extern int tgetnum (), tgetflag ();
+extern char *tgetstr ();
+extern char *tgoto ();
+
+#define Certainly_enough_space 2048 /* page 3, Section 1.1, para 4 */
+
+#if defined (unix)
+char termcap_buffer[Certainly_enough_space];
+#else /* !unix */
+#define termcap_buffer NULL
+#endif /* !unix */
+
+/* You CANNOT remove these next four vars. TERMCAP needs them to operate. */
+char PC;
+char *BC;
+char *UP;
+
+/* A huge array of stuff to get from termcap initialization. */
+
+#define tc_int 0
+#define tc_char tc_int+1
+#define tc_flag tc_char+1
+#define tc_last tc_flag+1
+
+typedef int flag;
+
+/* First, the variables which this array refers to */
+
+/* Capabilities */
+
+#if 0 /* partain moved them */
+int terminal_columns; /* {tc_int, "co" */
+int terminal_rows; /* {tc_int, "li" */
+#endif
+flag terminal_is_generic; /* {tc_flag,"gn" */
+
+ /* Cursor Motion */
+
+char *terminal_goto; /* {tc_char,"cm" */
+char *terminal_home; /* {tc_char,"ho" */
+
+char *terminal_cursor_left; /* {tc_char,"le" */
+char *terminal_cursor_right; /* {tc_char,"nd" */
+char *terminal_cursor_up; /* {tc_char,"up" */
+char *terminal_cursor_down; /* {tc_char,"do" */
+
+/* Screen Clearing */
+
+char *terminal_clearpage; /* {tc_char,"cl" */
+char *terminal_clearEOP; /* {tc_char,"cd" */
+char *terminal_clearEOL; /* {tc_char,"ce" */
+
+/* "Standout" */
+char *terminal_standout_begin; /* {tc_char,"so" */
+char *terminal_standout_end; /* {tc_char,"se" */
+
+/* Reverse Video */
+char *terminal_inverse_begin; /* {tc_char,"mr" */
+char *terminal_end_attributes; /* {tc_char,"me" */
+
+/* Ding! */
+
+char *terminal_ear_bell; /* {tc_char,"bl" */
+
+/* Terminal Initialization */
+
+char *terminal_use_begin; /* {tc_char,"ti" */
+char *terminal_use_end; /* {tc_char,"te" */
+
+/* Padding Stuff */
+
+char *terminal_padding; /* {tc_char,"pc" */
+
+/* Now the whopping big array */
+
+typedef struct {
+ char type;
+ char *name;
+ char *value;
+} termcap_capability_struct;
+
+termcap_capability_struct capabilities[] = {
+
+/* Capabilities */
+
+ {tc_int, "co", (char *) &terminal_columns},
+ {tc_int, "li", (char *) &terminal_rows},
+ {tc_flag, "gn", (char *) &terminal_is_generic},
+
+/* Cursor Motion */
+
+ {tc_char, "cm", (char *) &terminal_goto},
+ {tc_char, "ho", (char *) &terminal_home},
+
+ {tc_char, "le", (char *) &terminal_cursor_left},
+ {tc_char, "nd", (char *) &terminal_cursor_right},
+ {tc_char, "up", (char *) &terminal_cursor_up},
+ {tc_char, "do", (char *) &terminal_cursor_down},
+
+/* Screen Clearing */
+
+ {tc_char, "cl", (char *) &terminal_clearpage},
+ {tc_char, "cd", (char *) &terminal_clearEOP},
+ {tc_char, "ce", (char *) &terminal_clearEOL},
+
+/* "Standout" */
+ {tc_char, "so", (char *) &terminal_standout_begin},
+ {tc_char, "se", (char *) &terminal_standout_end},
+
+/* Reverse Video */
+ {tc_char, "mr", (char *) &terminal_inverse_begin},
+ {tc_char, "me", (char *) &terminal_end_attributes},
+
+/* Ding! */
+
+ {tc_char, "bl", (char *) &terminal_ear_bell},
+
+/* Terminal Initialization */
+
+ {tc_char, "ti", (char *) &terminal_use_begin},
+ {tc_char, "te", (char *) &terminal_use_end},
+
+/* Padding Stuff */
+
+ {tc_char, "pc", (char *) &terminal_padding},
+
+/* Terminate this array with a var of type tc_last */
+ {tc_last, NULL, NULL}
+
+};
+
+int terminal_opened_p = 0;
+
+open_terminal_io ()
+{
+ int error;
+
+ if (terminal_opened_p)
+ return (NO_ERROR);
+
+ if ((error = get_terminal_info ()) != NO_ERROR)
+ return (error);
+
+ if ((error = get_terminal_vars (capabilities)) != NO_ERROR)
+ return (error);
+
+ /* Now, make sure we have the capabilites that we need. */
+ if (terminal_is_generic)
+ return (BAD_TERMINAL);
+
+ terminal_opened_p++;
+ return (NO_ERROR);
+}
+
+get_terminal_info ()
+{
+ char temp_string_buffer[256];
+ int result;
+
+ char *terminal_name = getenv ("TERM");
+
+ if (terminal_name == NULL || *terminal_name == 0
+ || (strcmp (terminal_name, "dialup") == 0))
+ {
+ terminal_name = temp_string_buffer;
+ printf ("\nTerminal Type:");
+ fflush (stdout);
+ fgets (terminal_name, 256, stdin);
+ if (!(*terminal_name))
+ return (NO_TERMINAL_DESCRIPTOR);
+ }
+
+/* #define VERBOSE_GET_TERMINAL 1 */
+#ifdef VERBOSE_GET_TERMINAL
+
+#define buffer_limit 256
+#define opsys_termcap_filename "/etc/termcap"
+
+ /* We hack question mark if that is what the user typed. All this means
+ is we read /etc/termcap, and prettily print out the names of terminals
+ that we find. */
+
+ if (terminal_name[0] == '?' && !terminal_name[1])
+ {
+ FILE *termcap_file;
+ if ((termcap_file = fopen (opsys_termcap_filename, "r")) != NULL)
+ {
+ int result;
+ char line_buffer[buffer_limit];
+ int terminal_count = 0;
+
+ while ((readline_termcap (termcap_file, line_buffer)) != EOF)
+ {
+ char first_char = *line_buffer;
+ if (first_char == '#' || first_char == ' '
+ || first_char == '\t' || first_char == '\n')
+ ;
+ else
+ {
+ /* Print the names the pretty way. */
+ printf ("\n%s", line_buffer); /* liar */
+ terminal_count++;
+ }
+ }
+ fclose (termcap_file);
+
+ if (terminal_count)
+ printf ("\n%d terminals listed.\n", terminal_count);
+ else
+ printf ("\nNo terminals were listed. Brian's mistake.\n");
+ }
+ else
+ {
+ fprintf (stderr,
+ "\nNo such system file as %s!\nWe lose badly.\n",
+ opsys_termcap_filename);
+ return (NO_TERMINAL_DESCRIPTOR);
+ }
+ return (get_terminal_info ());
+ }
+#endif /* VERBOSE_GET_TERMINAL */
+
+ result = tgetent (termcap_buffer, terminal_name);
+
+ if (!result)
+ return (NO_TERMINAL_DESCRIPTOR);
+ else
+ return (NO_ERROR);
+}
+
+#ifdef VERBOSE_GET_TERMINAL
+readline_termcap (stream, buffer)
+ FILE *stream;
+ char *buffer;
+{
+ int c;
+ int buffer_index = 0;
+
+ while ((c = getc (stream)) != EOF && c != '\n')
+ {
+ if (buffer_index != buffer_limit - 1)
+ buffer[buffer_index++] = c;
+ }
+
+ buffer[buffer_index] = 0;
+
+ if (c == EOF)
+ return ((buffer_index) ? 0 : EOF);
+ else
+ return (0);
+}
+#endif /* VERBOSE_GET_TERMINAL */
+
+/* For each element of "from_array", read the corresponding variable's
+ value into the right place. */
+get_terminal_vars (from_array)
+ termcap_capability_struct from_array[];
+{
+ int i;
+ register termcap_capability_struct *item;
+ char *buffer;
+
+#if !defined (GNU_TERMCAP)
+ buffer = (char *) xmalloc (sizeof (termcap_buffer) + 1);
+# define buffer_space &buffer
+#else
+# define buffer_space 0
+#endif
+
+ for (i = 0; (item = &from_array[i]) && (item->type != tc_last); i++)
+ {
+ switch (item->type)
+ {
+ case tc_int:
+ *((int *) (item->value)) = tgetnum (item->name);
+ break;
+
+ case tc_flag:
+ *((int *) item->value) = tgetflag (item->name);
+ break;
+
+ case tc_char:
+ *((char **) item->value) = tgetstr (item->name, buffer_space);
+ break;
+
+ default:
+ FERROR ("Bad entry scanned in tc_struct[].\n \
+ Ask bfox@ai.mit.edu to fix this someday.\n");
+ }
+ }
+
+ PC = terminal_padding ? terminal_padding[0] : 0;
+ BC = terminal_cursor_left;
+ UP = terminal_cursor_up;
+ return (NO_ERROR);
+}
+
+/* Return the number of rows this terminal has. */
+int
+get_terminal_rows ()
+{
+ int rows = 0;
+
+#if defined (TIOCGWINSZ)
+ {
+ int tty;
+ struct winsize size;
+
+ tty = fileno (stdin);
+
+ if (ioctl (tty, TIOCGWINSZ, &size) != -1)
+ rows = size.ws_row;
+ }
+#endif /* TIOCGWINSZ */
+
+ if (!rows)
+ rows = tgetnum ("li");
+
+ if (rows <= 0)
+ rows = 24;
+
+ return (rows);
+}
+
+/* Return the number of columns this terminal has. */
+get_terminal_columns ()
+{
+ int columns = 0;
+
+#if defined (TIOCGWINSZ)
+ {
+ int tty;
+ struct winsize size;
+
+ tty = fileno (stdin);
+
+ if (ioctl (tty, TIOCGWINSZ, &size) != -1)
+ columns = size.ws_col;
+ }
+#endif /* TIOCGWINSZ */
+
+ if (!columns)
+ columns = tgetnum ("co");
+
+ if (columns <= 0)
+ columns = 80;
+
+ return (columns);
+}
+
+/* #define TERMINAL_INFO_PRINTING */
+#ifdef TERMINAL_INFO_PRINTING
+
+/* Scan this (already "get_terminal_vars"ed) array, printing out the
+ capability name, and value for each entry. Pretty print the value
+ so that the terminal doesn't actually do anything, shitbrain. */
+show_terminal_info (from_array)
+ termcap_capability_struct from_array[];
+{
+ register int i;
+ register termcap_capability_struct *item;
+
+ for (i = 0; ((item = &from_array[i]) && ((item->type) != tc_last)); i++)
+ {
+
+ char *type_name;
+ switch (item->type)
+ {
+ case tc_int:
+ type_name = "int ";
+ break;
+ case tc_flag:
+ type_name = "flag";
+ break;
+ case tc_char:
+ type_name = "char";
+ break;
+ default:
+ type_name = "Broken";
+ }
+
+ printf ("\t%s\t%s = ", type_name, item->name);
+
+ switch (item->type)
+ {
+ case tc_int:
+ case tc_flag:
+ printf ("%d", *((int *) item->value));
+ break;
+ case tc_char:
+ tc_pretty_print (*((char **) item->value));
+ break;
+ }
+ printf ("\n");
+ }
+}
+
+/* Print the contents of string without sending anything that isn't
+ a normal printing ASCII character. */
+tc_pretty_print (string)
+ register char *string;
+{
+ register char c;
+
+ while (c = *string++)
+ {
+ if (CTRLP (c))
+ {
+ putchar ('^');
+ c += 64;
+ }
+ putchar (c);
+ }
+}
+#endif /* TERMINAL_INFO_PRINTING */
+
+
+/* **************************************************************** */
+/* */
+/* Character IO, and driver */
+/* */
+/* **************************************************************** */
+
+int terminal_inited_p = 0;
+
+/* Start up the character io stuff. */
+init_terminal_io ()
+{
+ if (!terminal_inited_p)
+ {
+ opsys_init_terminal ();
+ terminal_rows = get_terminal_rows ();
+ terminal_columns = get_terminal_columns ();
+
+ widest_line = (char *) xmalloc (terminal_columns);
+
+ terminal_inited_p = 1;
+ }
+
+ terminal_window.left = 0;
+ terminal_window.top = 0;
+ terminal_window.right = terminal_columns;
+ terminal_window.bottom = terminal_rows;
+
+ set_window (&terminal_window);
+
+ terminal_window.bottom -= 2;
+
+ set_window (&terminal_window);
+
+ init_echo_area (the_window.left, the_window.bottom + 1,
+ the_window.right, terminal_rows);
+
+ /* Here is a list of things that the terminal has to be able to do. Do
+ you think that this is too harsh? */
+ if (!terminal_goto || /* We can't move the cursor. */
+ !terminal_rows) /* We don't how many lines it has. */
+ {
+ fprintf (stderr,
+ "Your terminal is not clever enough to run info. Sorry.\n");
+ exit (1);
+ }
+}
+
+/* Ring the terminal bell. */
+ding ()
+{
+ extern char *terminal_ear_bell;
+
+ if (terminal_ear_bell)
+ do_term (terminal_ear_bell);
+ else
+ putchar (CTRL ('G'));
+
+ fflush (stdout);
+}
+
+int untyi_char = 0;
+int inhibit_output = 0;
+
+/* Return a character from stdin, or the last unread character
+ if there is one available. */
+blink_cursor ()
+{
+ int character;
+
+ fflush (stdout);
+ if (untyi_char)
+ {
+ character = untyi_char;
+ untyi_char = 0;
+ }
+ else
+ do { character = getc (stdin); } while (character == -1 && errno == EINTR);
+
+ return (character);
+}
+
+/* Display single character on the terminal screen. If the
+ character would run off the right hand edge of the screen,
+ advance the cursor to the next line. */
+charout (character)
+ int character;
+{
+ if (inhibit_output)
+ return;
+
+ /* This character may need special treatment if it is
+ a control character. */
+ if (CTRL_P (character))
+ {
+ switch (character)
+ {
+ case NEWLINE:
+ case RETURN:
+ print_cr ();
+ break;
+
+ case TAB:
+ print_tab ();
+ break;
+
+ default:
+ charout ('^');
+ charout (UNCTRL (character));
+ }
+ }
+ else
+ {
+ putchar (character);
+ advance (1);
+ }
+}
+
+/* Move the cursor AMOUNT character positions. */
+advance (amount)
+ int amount;
+{
+ int old_window_cv = the_window.cv;
+
+ while (amount-- > 0)
+ {
+ the_window.ch++;
+ if (the_window.ch >= the_window.right)
+ {
+ the_window.ch = (the_window.ch - the_window.right) + the_window.left;
+ the_window.cv++;
+
+ if (the_window.cv >= the_window.bottom)
+ the_window.cv = the_window.top;
+ }
+ }
+
+ if (the_window.cv != old_window_cv)
+ goto_xy (the_window.ch, the_window.cv);
+}
+
+/* Print STRING and args using charout */
+print_string (string, a1, a2, a3, a4, a5)
+ char *string;
+{
+ int character;
+ char buffer[2048];
+ int idx = 0;
+
+ sprintf (buffer, string, a1, a2, a3, a4, a5);
+
+ while (character = buffer[idx++])
+ charout (character);
+
+ fflush (stdout);
+}
+
+/* Display a carriage return.
+ Clears to the end of the line first. */
+print_cr ()
+{
+ extern int typing_out;
+ clear_eol ();
+
+ if (typing_out)
+ { /* Do the "MORE" stuff. */
+ int response;
+
+ if (the_window.cv + 2 == the_window.bottom)
+ {
+ goto_xy (the_window.left, the_window.cv + 1);
+ clear_eol ();
+ print_string ("[More]");
+ response = blink_cursor ();
+ if (response != SPACE)
+ {
+ untyi_char = response;
+ inhibit_output = 1;
+ return;
+ }
+ else
+ {
+ goto_xy (the_window.left, the_window.cv);
+ clear_eol ();
+ goto_xy (the_window.left, the_window.top);
+ return;
+ }
+ }
+ }
+ advance (the_window.right - the_window.ch);
+}
+
+/* Move the cursor to the next tab stop, blanking the intervening
+ spaces along the way. */
+print_tab ()
+{
+ int hpos, width, destination;
+
+ hpos = the_window.ch - the_window.left;
+ width = ((hpos + 8) & 0xf8) - hpos;
+
+ destination = hpos + width + the_window.left;
+
+ if (destination >= the_window.right)
+ destination -= the_window.right;
+
+ while (the_window.ch != destination)
+ charout (SPACE);
+}
+
+display_width (character, hpos)
+ int character, hpos;
+{
+ int width = 1;
+
+ if (CTRL_P (character))
+ {
+ switch (character)
+ {
+ case RETURN:
+ case NEWLINE:
+ width = the_window.right - hpos;
+ break;
+ case TAB:
+ width = ((hpos + 8) & 0xf8) - hpos;
+ break;
+ default:
+ width = 2;
+ }
+ }
+ return (width);
+}
+
+/* Like GOTO_XY, but do it right away. */
+I_goto_xy (xpos, ypos)
+ int xpos, ypos;
+{
+ goto_xy (xpos, ypos);
+ fflush (stdout);
+}
+
+/* Move the cursor, (and cursor variables) to xpos, ypos. */
+goto_xy (xpos, ypos)
+ int xpos, ypos;
+{
+ the_window.ch = xpos;
+ the_window.cv = ypos;
+ opsys_goto_pos (xpos, ypos);
+}
+
+/* Clear the screen, leaving ch and cv at the top of the window. */
+clear_screen ()
+{
+ goto_xy (the_window.left, the_window.top);
+ clear_eop_slowly ();
+}
+
+clear_eop_slowly ()
+{
+ int temp_ch = the_window.ch;
+ int temp_cv = the_window.cv;
+
+ clear_eol ();
+
+ while (++the_window.cv < the_window.bottom)
+ {
+ goto_xy (the_window.left, the_window.cv);
+ clear_eol ();
+ }
+ goto_xy (temp_ch, temp_cv);
+}
+
+/* Clear from current cursor position to end of page. */
+clear_eop ()
+{
+ if (terminal_clearEOP)
+ do_term (terminal_clearEOP);
+ else
+ clear_eop_slowly ();
+}
+
+/* Clear from current cursor position to end of screen line */
+clear_eol ()
+{
+ int temp_ch = the_window.ch;
+
+ if (terminal_clearEOL)
+ do_term (terminal_clearEOL);
+ else
+ {
+ char *line = widest_line;
+ int i;
+
+ for (i = 0; i < the_window.right - the_window.ch; i++)
+ line[i] = ' ';
+ line[i] = '\0';
+
+ printf ("%s", line);
+ }
+ goto_xy (temp_ch, the_window.cv);
+}
+
+/* Call FUNCTION with WINDOW active. You can pass upto 5 args to the
+ function. This returns whatever FUNCTION returns. */
+int
+with_output_to_window (window, function, arg1, arg2, arg3, arg4, arg5)
+ WINDOW *window;
+ Function *function;
+{
+ int result;
+
+ push_window ();
+ set_window (window);
+ result = (*function) (arg1, arg2, arg3, arg4, arg5);
+ pop_window ();
+ return (result);
+}
+
+/* Given a pointer to a window data structure, make that
+ the current window. */
+set_window (window)
+ WINDOW *window;
+{
+ bcopy (window, &the_window, sizeof (WINDOW));
+}
+
+/* Save the current window on the window stack. */
+push_window ()
+{
+ WINDOW_LIST *new_window = (WINDOW_LIST *) xmalloc (sizeof (WINDOW_LIST));
+
+ new_window->next_window = window_stack;
+ window_stack = new_window;
+ new_window->ch = the_window.ch;
+ new_window->cv = the_window.cv;
+ new_window->top = the_window.top;
+ new_window->bottom = the_window.bottom;
+ new_window->left = the_window.left;
+ new_window->right = the_window.right;
+}
+
+/* Pop the top of the window_stack into the_window. */
+pop_window ()
+{
+ set_window ((WINDOW *)window_stack);
+
+ if (window_stack->next_window)
+ {
+ WINDOW_LIST *thing_to_free = window_stack;
+ window_stack = window_stack->next_window;
+ free (thing_to_free);
+ }
+
+ goto_xy (the_window.ch, the_window.cv);
+}
+
+/* **************************************************************** */
+/* */
+/* "Opsys" functions. */
+/* */
+/* **************************************************************** */
+
+/* The lowlevel terminal/file interface. Nothing ever really gets
+ low level when you're writing in C, though.
+
+ This file contains all of the "opsys" labels. You have to make
+ a different one if you want GNU Info to run on machines that don't
+ have Unix. */
+
+extern char *terminal_use_begin, *terminal_use_end, *terminal_goto;
+
+#if defined (TIOCGETC)
+struct tchars original_tchars;
+#endif
+
+#if defined (TIOCGLTC)
+struct ltchars original_ltchars;
+#endif
+
+#if defined (USG)
+struct termio original_termio, ttybuff;
+#else
+int original_tty_flags = 0;
+int original_lmode;
+struct sgttyb ttybuff;
+#endif /* !USG */
+
+/* Yes, that's right, do things that the machine needs to get
+ the terminal into a usable mode. */
+opsys_init_terminal ()
+{
+ int tty = fileno (stdin);
+
+#if defined (USG)
+ ioctl (tty, TCGETA, &original_termio);
+ ioctl (tty, TCGETA, &ttybuff);
+ ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL &~IXON);
+ ttybuff.c_oflag &= (~ONLCR & ~OCRNL);
+ ttybuff.c_lflag &= (~ICANON & ~ECHO);
+
+ ttybuff.c_cc[VMIN] = 1;
+ ttybuff.c_cc[VTIME] = 0;
+
+ if (ttybuff.c_cc[VINTR] = DELETE)
+ ttybuff.c_cc[VINTR] = -1;
+
+ if (ttybuff.c_cc[VQUIT] = DELETE)
+ ttybuff.c_cc[VQUIT] = -1;
+
+ ioctl (tty, TCSETA, &ttybuff);
+#else /* !USG */
+
+ ioctl (tty, TIOCGETP, &ttybuff);
+
+ if (!original_tty_flags)
+ original_tty_flags = ttybuff.sg_flags;
+
+ /* Make this terminal pass 8 bits around while we are using it. */
+#ifdef PASS8
+ ttybuff.sg_flags |= PASS8;
+#endif
+
+#if defined (TIOCLGET) && defined (LPASS8)
+ {
+ int flags;
+ ioctl (tty, TIOCLGET, &flags);
+ original_lmode = flags;
+ flags |= LPASS8;
+ ioctl (tty, TIOCLSET, &flags);
+ }
+#endif
+
+#ifdef TIOCGETC
+ {
+ struct tchars temp;
+
+ ioctl (tty, TIOCGETC, &original_tchars);
+ bcopy (&original_tchars, &temp, sizeof (struct tchars));
+
+ temp.t_startc = temp.t_stopc = -1;
+
+ /* If the quit character conflicts with one of our commands, then
+ make it go away. */
+ if (temp.t_intrc == DELETE)
+ temp.t_intrc == -1;
+
+ if (temp.t_quitc == DELETE)
+ temp.t_quitc == -1;
+
+ ioctl (tty, TIOCSETC, &temp);
+ }
+#endif /* TIOCGETC */
+
+#ifdef TIOCGLTC
+ {
+ struct ltchars temp;
+
+ ioctl (tty, TIOCGLTC, &original_ltchars);
+ bcopy (&original_ltchars, &temp, sizeof (struct ltchars));
+
+ /* Make the interrupt keys go away. Just enough to make people happy. */
+ temp.t_lnextc = -1; /* C-v */
+
+ ioctl (tty, TIOCSLTC, &temp);
+ }
+#endif /* TIOCGLTC */
+
+ ttybuff.sg_flags &= ~ECHO;
+ ttybuff.sg_flags |= CBREAK;
+ ioctl (tty, TIOCSETN, &ttybuff);
+#endif /* !USG */
+
+ open_terminal_io ();
+ do_term (terminal_use_begin);
+}
+
+/* Fix the terminal that I broke. */
+restore_io ()
+{
+ int tty = fileno (stdin);
+
+#if defined (USG)
+ ioctl (tty, TCSETA, &original_termio);
+#else
+ ioctl (tty, TIOCGETP, &ttybuff);
+ ttybuff.sg_flags = original_tty_flags;
+ ioctl (tty, TIOCSETN, &ttybuff);
+
+#ifdef TIOCGETC
+ ioctl (tty, TIOCSETC, &original_tchars);
+#endif /* TIOCGETC */
+
+#ifdef TIOCGLTC
+ ioctl (tty, TIOCSLTC, &original_ltchars);
+#endif /* TIOCGLTC */
+
+#if defined (TIOCLGET) && defined (LPASS8)
+ ioctl (tty, TIOCLSET, &original_lmode);
+#endif
+
+#endif /* !USG */
+ do_term (terminal_use_end);
+}
+
+opsys_goto_pos (xpos, ypos)
+ int xpos, ypos;
+{
+ do_term (tgoto (terminal_goto, xpos, ypos));
+}
+
+character_output_function (character)
+ char character;
+{
+ putchar (character);
+}
+
+/* Generic interface to tputs. */
+do_term (command)
+ char *command;
+{
+ /* Send command to the terminal, with appropriate padding. */
+ if (command)
+ tputs (command, 1, character_output_function);
+}
+
+/* Filename manipulators, and the like. */
+char local_temp_filename[FILENAME_LEN];
+
+char *info_suffixes[] = {
+ "",
+ ".info",
+ "-info",
+ (char *)NULL
+};
+
+/* A structure which associates the argument passed into a function with
+ the result from that function. */
+typedef struct {
+ char *called;
+ char *result;
+} CALLED_RESULTS;
+
+/* An array of remembered arguments and results. */
+static CALLED_RESULTS **opsys_callers_and_results = (CALLED_RESULTS **)NULL;
+static int next_caller_and_result = 0;
+static int callers_and_results_size = 0;
+
+/* Find the result for having already called opsys_filename () with CALLER. */
+char *
+find_opsys_filename_result (caller)
+ char *caller;
+{
+ if (caller && opsys_callers_and_results)
+ {
+ register int i;
+ for (i = 0; opsys_callers_and_results[i]; i++)
+ {
+ if (strcmp (opsys_callers_and_results[i]->called, caller) == 0)
+ return (opsys_callers_and_results[i]->result);
+ }
+ }
+ return (char *)NULL;;
+}
+
+/* Add an argument and result to our list. */
+void
+add_caller_and_result (caller, result)
+ char *caller, *result;
+{
+ CALLED_RESULTS *new;
+
+ if (next_caller_and_result + 2 > callers_and_results_size)
+ {
+ int alloc_size;
+ callers_and_results_size += 10;
+
+ alloc_size = callers_and_results_size * sizeof (CALLED_RESULTS *);
+
+ opsys_callers_and_results = (CALLED_RESULTS **)
+ xrealloc (opsys_callers_and_results, alloc_size);
+ }
+
+ new = (CALLED_RESULTS *)xmalloc (sizeof (CALLED_RESULTS));
+ new->called = savestring (caller);
+ new->result = result ? savestring (result) : (char *)NULL;
+
+ opsys_callers_and_results[next_caller_and_result++] = new;
+ opsys_callers_and_results[next_caller_and_result] = (CALLED_RESULTS *)NULL;
+}
+
+/* Expand the filename in partial to make a real name for
+ this operating system. This looks in INFO_PATHS in order to
+ find the correct file. If it can't find the file, it just
+ returns the path as you gave it. */
+char *
+opsys_filename (partial)
+ char *partial;
+{
+ int initial_character;
+ char *my_infopath;
+
+ if (partial && (initial_character = *partial))
+ {
+ char *possible_result;
+
+ if (initial_character == '/')
+ return (partial);
+
+ possible_result = find_opsys_filename_result (partial);
+ if (possible_result)
+ return (possible_result);
+
+ if (initial_character == '~')
+ {
+ if (partial[1] == '/')
+ {
+ /* Return the concatenation of HOME and the rest
+ of the string. */
+ strcpy (local_temp_filename, getenv ("HOME"));
+ strcat (local_temp_filename, &partial[2]);
+ return (local_temp_filename);
+ }
+ else
+ {
+ struct passwd *user_entry;
+ int i, c;
+ char username[257];
+
+ for (i = 1; c = partial[i]; i++)
+ {
+ if (c == '/')
+ break;
+ else
+ username[i - 1] = c;
+ }
+ username[i - 1] = '\0';
+
+ if (!(user_entry = getpwnam (username)))
+ {
+ display_error ("Not a registered user!");
+ return (partial);
+ }
+ strcpy (local_temp_filename, user_entry->pw_dir);
+ strcat (local_temp_filename, &partial[i]);
+ return (local_temp_filename);
+ }
+ }
+
+ if (initial_character == '.' &&
+ (partial[1]) == '/' || (partial[1] == '.' && partial[2] == '/'))
+ {
+#if defined (USG)
+ if (!getcwd (local_temp_filename, FILENAME_LEN))
+#else
+ if (!getwd (local_temp_filename))
+#endif
+ {
+ display_error (local_temp_filename);
+ return (partial);
+ }
+
+ strcat (local_temp_filename, "/");
+ strcat (local_temp_filename, partial);
+ return (local_temp_filename);
+ }
+
+ /* If the current info file has a directory, then search that directory
+ first. */
+ {
+ register char *ptr, *file;
+
+ file = find_opsys_filename_result (current_info_file);
+
+ if (file && (ptr = (char *)rindex (file, '/')) != (char *)NULL)
+ {
+ register int len = (ptr - file);
+
+ my_infopath = (char *)
+ xmalloc (2 + strlen (file) + strlen (infopath));
+
+ strncpy (my_infopath, file, len);
+ sprintf (my_infopath + len, ":%s", infopath);
+ }
+ else
+ my_infopath = savestring (infopath);
+ }
+
+ if (opsys_info_file_in_path (partial, my_infopath, local_temp_filename))
+ {
+ free (my_infopath);
+ add_caller_and_result (partial, local_temp_filename);
+ return (local_temp_filename);
+ }
+
+ free (my_infopath);
+ }
+ return (partial);
+}
+
+#if !defined (S_ISREG) && defined (S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif /* !S_ISREG && S_IFREG */
+
+#if !defined (S_ISDIR) && defined (S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif /* !S_ISDIR && S_IFDIR */
+
+/* Scan the list of directories in PATH looking for FILENAME.
+ If we find one that is a regular file, stuff the answer into
+ RETURN_STRING. Return non-zero if a file was found, zero otherwise. */
+int
+opsys_info_file_in_path (filename, path, return_string)
+ char *filename, *path;
+ char *return_string;
+{
+ struct stat finfo;
+ char *temp_dirname, *extract_colon_unit ();
+ char *test_file = return_string;
+ int statable, dirname_index = 0;
+
+ while (temp_dirname = extract_colon_unit (path, &dirname_index))
+ {
+ register int i, pre_suffix_length;
+
+ strcpy (test_file, temp_dirname);
+ if (temp_dirname[(strlen (temp_dirname)) - 1] != '/')
+ strcat (test_file, "/");
+ strcat (test_file, filename);
+
+ pre_suffix_length = strlen (test_file);
+
+ free (temp_dirname);
+
+ for (i = 0; info_suffixes[i]; i++)
+ {
+ strcpy (test_file + pre_suffix_length, info_suffixes[i]);
+
+ statable = (stat (test_file, &finfo) == 0);
+
+ /* If we have found a regular file, then use that. Else, if we
+ have found a directory, look in that directory for this file. */
+ if (statable)
+ {
+ if (S_ISREG (finfo.st_mode))
+ return (1);
+ else if (S_ISDIR (finfo.st_mode))
+ {
+ char *newpath = savestring (test_file);
+ char *filename_only = (char *)rindex (filename, '/');
+
+ if (opsys_info_file_in_path
+ (filename_only ? filename_only : filename,
+ newpath, return_string))
+ {
+ free (newpath);
+ return (1);
+ }
+ }
+ }
+ }
+ }
+ return (0);
+}
+
+/* Given a string containing units of information separated by colons,
+ return the next one pointed to by IDX, or NULL if there are no more.
+ Advance IDX to the character after the colon. */
+char *
+extract_colon_unit (string, idx)
+ char *string;
+ int *idx;
+{
+ register int i, start;
+
+ i = start = *idx;
+ if ((i >= strlen (string)) || !string)
+ return ((char *) NULL);
+
+ while (string[i] && string[i] != ':')
+ i++;
+ if (i == start)
+ {
+ return ((char *) NULL);
+ }
+ else
+ {
+ char *value = (char *) xmalloc (1 + (i - start));
+ strncpy (value, &string[start], (i - start));
+ value[i - start] = '\0';
+ if (string[i])
+ ++i;
+ *idx = i;
+ return (value);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* The echo area. */
+/* */
+/* **************************************************************** */
+
+WINDOW echo_area = {0, 0, 0, 0, 0, 0};
+int echo_area_open_p = 0;
+char modeline[256];
+WINDOW modeline_window = {0, 0, 0, 0, 0, 0};
+
+/* Define the location of the echo area. Also inits the
+ modeline as well. */
+init_echo_area (left, top, right, bottom)
+ int left, top, right, bottom;
+{
+ echo_area.left = modeline_window.left = left;
+ echo_area.top = top;
+ modeline_window.top = top - 1;
+ echo_area.right = modeline_window.right = right;
+ echo_area.bottom = bottom;
+ modeline_window.bottom = modeline_window.top;
+}
+
+/* Make the echo_area_window be the current window, and only allow
+ output in there. Clear the window to start. */
+new_echo_area ()
+{
+ if (!echo_area_open_p)
+ {
+ push_window ();
+ set_window (&echo_area);
+ echo_area_open_p = 1;
+ }
+ goto_xy (the_window.left, the_window.top);
+ clear_eop ();
+}
+
+/* Return output to the previous window. */
+close_echo_area ()
+{
+ if (!echo_area_open_p)
+ return;
+
+ pop_window ();
+ echo_area_open_p = 0;
+}
+
+/* Clear the contents of the echo area. */
+clear_echo_area ()
+{
+ new_echo_area ();
+ close_echo_area ();
+}
+
+/* Create and display the modeline. */
+make_modeline ()
+{
+ int width = modeline_window.right - modeline_window.left;
+ char textual_position[6];
+
+ if (pagetop == nodetop)
+ {
+ if (pagebot == nodebot)
+ sprintf (textual_position, "All");
+ else
+ sprintf (textual_position, "Top");
+ }
+ else
+ {
+ if (pagebot == nodebot)
+ sprintf (textual_position, "Bot");
+ else
+ sprintf (textual_position, "%2d%%",
+ 100 * (pagetop - nodetop) / (nodebot - nodetop));
+ }
+
+ sprintf (modeline, "Info: (%s)%s, %d lines ---%s",
+ current_info_file, current_info_node, nodelines, textual_position);
+
+ if (strnicmp
+ (opsys_filename (current_info_file), last_loaded_info_file,
+ strlen (last_loaded_info_file)) != 0)
+ {
+ sprintf (&modeline[strlen (modeline)], ", Subfile: %s",
+ last_loaded_info_file);
+ }
+
+ if (strlen (modeline) < width)
+ {
+ int idx = strlen (modeline);
+ while (idx != width)
+ modeline[idx++] = '-';
+ modeline[idx] = '\0';
+ }
+
+ if (strlen (modeline) > width)
+ modeline[width] = '\0';
+ push_window ();
+ set_window (&modeline_window);
+ goto_xy (the_window.left, the_window.top);
+
+ if (terminal_inverse_begin)
+ do_term (terminal_inverse_begin);
+ print_string ("%s", modeline);
+ if (terminal_inverse_begin)
+ do_term (terminal_end_attributes);
+
+ pop_window ();
+}
+
+int typing_out = 0;
+
+/* Prepare to do output to the typeout window. If the
+ typeout window is already open, ignore this clown. */
+open_typeout ()
+{
+ if (typing_out)
+ return;
+
+ push_window ();
+ set_window (&terminal_window);
+ goto_xy (the_window.ch, the_window.cv);
+ typing_out = window_bashed = 1;
+}
+
+/* Close the currently open typeout window. */
+close_typeout ()
+{
+ if (inhibit_output)
+ inhibit_output = 0;
+ else
+ {
+ do { untyi_char = getc (stdin); }
+ while (untyi_char == -1 && errno == EINTR);
+
+ if (untyi_char == SPACE)
+ untyi_char = 0;
+ }
+ pop_window ();
+ typing_out = 0;
+}
+
+void *
+xrealloc (pointer, bytes)
+ char *pointer;
+ int bytes;
+{
+ void *temp;
+
+ if (pointer == (char *)NULL)
+ temp = (void *) xmalloc (bytes);
+ else
+ temp = (void *) realloc (pointer, bytes);
+
+ if (temp == (void *)NULL)
+ {
+ fprintf (stderr, "Virtual memory exhausted\n");
+ restore_io ();
+ exit (2);
+ }
+ return (temp);
+}
+
+void *
+xmalloc (bytes)
+ int bytes;
+{
+ void *temp = (void *) malloc (bytes);
+
+ if (temp == (void *) NULL)
+ {
+ fprintf (stderr, "Virtual memory exhausted\n");
+ restore_io ();
+ exit (2);
+ }
+ return (temp);
+}
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/info.el b/web/glasgow/lit2x-0.16/literate/info-utils/info.el
new file mode 100644
index 0000000000..00e7146230
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/info.el
@@ -0,0 +1,1910 @@
+;; Info package for Emacs -- Dave Gillespie's version 1.05 of 3/8/92.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; This is based on the version 19 info.el file.
+;;
+;; Note that Info-directory has been replaced by Info-directory-list,
+;; a search path of directories in which to find Info files.
+;; Also, Info tries adding ".info" to a file name if the name itself
+;; is not found.
+;;
+;; This file also has several small bug fixes compared to the 18.57 version.
+
+
+;; LCD Archive Entry:
+;; info-dg|Dave Gillespie|daveg@synaptics.com
+;; |Info reader with many enhancements; replaces standard info.el.
+;; |92-03-08|1.05|~/modes/info.el
+
+;; Also available from anonymous FTP on csvax.cs.caltech.edu.
+
+
+;; Modified 3/7/1991 by Dave Gillespie:
+;; (Author's address: daveg@synaptics.com or daveg@csvax.cs.caltech.edu)
+;;
+;; Added keys: i, t, <, >, [, ], {, }, 6, 7, 8, 9, 0.
+;; Look at help for info-mode (type ? in Info) for descriptions.
+;;
+;; If Info-directory-list is undefined and there is no INFOPATH
+;; in the environment, use value of Info-directory for compatibility
+;; with Emacs 18.57.
+;;
+;; All files named "localdir" found in the path are appended to "dir",
+;; the Info directory. For this to work, "dir" should contain only
+;; one node (Top), and each "localdir" should contain no ^_ or ^L
+;; characters. Generally they will contain only one or several
+;; additional lines for the top-level menu. Note that "dir" is
+;; modified in memory each time it is loaded, but not on disk.
+;;
+;; If "dir" contains a line of the form: "* Locals:"
+;; then the "localdir"s are inserted there instead of at the end.
+
+
+;; Modified 4/3/1991 by Dave Gillespie:
+;;
+;; Added Info-mode-hook (suggested by Sebastian Kremer).
+;; Also added epoch-info-startup/select-hooks from Simon Spero's info.el.
+;;
+;; Added automatic decoding of compressed Info files.
+;; See documentation for the variable Info-suffix-list. Default is to
+;; run "uncompress" on ".Z" files and "unyabba" on ".Y" files.
+;; (See comp.sources.unix v24i073-076 for yabba/unyabba, a free software
+;; alternative to compress/uncompress.)
+;; Note: "dir" and "localdir" files should not be compressed.
+;;
+;; Changed variables like Info-enable-edit to be settable by M-x set-variable.
+;;
+;; Added Info-auto-advance variable. If t, SPC and DEL will act like
+;; } and {, i.e., they advance to the next/previous node if at the end
+;; of the buffer.
+;;
+;; Changed `u' to restore point to most recent location in that node.
+;; Added `=' to do this manually at any time. (Suggested by David Fox).
+;;
+;; Changed `m' and `0-9' to try interpreting menu name as a file name
+;; if not found as a node name. This allows (dir) menus of the form,
+;; Emacs:: Cool text editor
+;; as a shorthand for
+;; Emacs:(emacs). Cool text editor
+;;
+;; Enhanced `i' to use line-number information in the index.
+;; Added `,' to move among all matches to a previous `i' command.
+;;
+;; Added `a' (Info-annotate) for adding personal notes to any Info node.
+;; Notes are not stored in the actual Info files, but in the user's own
+;; ~/.infonotes file.
+;;
+;; Added Info-footnote-tag, made default be "Ref" instead of "Note".
+;;
+;; Got mouse-click stuff to work under Emacs version 18. Check it out!
+;; Left and right clicks scroll the Info window.
+;; Middle click goes to clicked-on node, e.g., "Next:", a menu, or a note.
+
+
+;; Modified 6/29/1991 by Dave Gillespie:
+;;
+;; Renamed epoch-info-startup/select-hooks to Info-startup/select-hook.
+;;
+;; Made Info-select-node into a command on the `!' key.
+;;
+;; Added Info-mouse-support user option.
+;;
+;; Cleaned up the implementation of some routines.
+;;
+;; Added special treatment of quoted words in annotations: The `g'
+;; command for a nonexistent node name scans for an annotation
+;; (in any node of any file) containing that name in quotes: g foo RET
+;; looks for an annotation containing: "foo"
+;; If found, it goes to that file and node.
+;;
+;; Added a call to set up Info-directory-list in Info-find-node to
+;; work around a bug in GNUS where it calls Info-goto-node before info.
+;;
+;; Added completion for `g' command (inspired by Richard Kim's infox.el).
+;; Completion knows all node names for the current file, and all annotation
+;; tags (see above). It does not complete file names or node names in
+;; other files.
+;;
+;; Added `k' (Info-emacs-key) and `*' (Info-elisp-ref) commands. You may
+;; wish to bind these to global keys outside of Info mode.
+;;
+;; Allowed localdir files to be full dir-like files; only the menu part
+;; of each localdir is copied. Also, redundant menu items are omitted.
+;;
+;; Changed Info-history to hold only one entry at a time for each node,
+;; and to be circular so that multiple `l's come back again to the most
+;; recent node. Note that the format of Info-history entries has changed,
+;; which may interfere with external programs that try to operate on it.
+;; (Also inspired by Kim's infox.el).
+;;
+;; Changed `n', `]', `l', etc. to accept prefix arguments to move several
+;; steps at once. Most accept negative arguments to move oppositely.
+;;
+;; Changed `?' to bury *Help* buffer afterwards to keep it out of the way.
+;;
+;; Rearranged `?' key's display to be a little better for new users.
+;;
+;; Changed `a' to save whole window configuration and restore on C-c C-c.
+;;
+;; Fixed the bug reported by Bill Reynolds on gnu.emacs.bugs.
+;;
+;; Changed Info-last to restore window-start as well as cursor position.
+;;
+;; Changed middle mouse button in space after end of node to do Info-last
+;; if we got here by following a cross reference, else do Info-global-next.
+;;
+;; Added some new mouse bindings: shift-left = Info-global-next,
+;; shift-right = Info-global-prev, shift-middle = Info-last.
+;;
+;; Fixed Info-follow-reference not to make assumptions about length
+;; of Info-footnote-tag [Linus Tolke].
+;;
+;; Changed default for Info-auto-advance mode to be press-twice-for-next-node.
+;;
+;; Modified x-mouse-ignore to preserve last-command variable, so that
+;; press-twice Info-auto-advance mode works with the mouse.
+
+
+;; Modified 3/4/1992 by Dave Gillespie:
+;;
+;; Added an "autoload" command to help autoload.el.
+;;
+;; Changed `*' command to look for file `elisp' as well as for `lispref'.
+;;
+;; Fixed a bug involving footnote names containing regexp special characters.
+;;
+;; Fixed a bug in completion during `f' (or `r') command.
+;;
+;; Added TAB (Info-next-reference), M-TAB, and RET keys to Info mode.
+;;
+;; Added new bindings, `C-h C-k' for Info-emacs-key and `C-h C-f' for
+;; Info-elisp-ref. These bindings are made when info.el is loaded, and
+;; only if those key sequences were previously unbound. These bindings
+;; work at any time, not just when Info is already running.
+
+
+;; Modified 3/8/1992 by Dave Gillespie:
+;;
+;; Fixed some long lines that were causing trouble with mailers.
+
+
+
+(provide 'info)
+
+(defvar Info-mouse-support t
+ "*Non-nil means to install Info mouse drivers for Emacs version 18.
+Set this to nil if you have your own Info mouse support.")
+
+(defvar Info-history nil
+ "List of info nodes user has visited.
+Each element of list is a list (\"(FILENAME)NODENAME\" BUFPOS WINSTART).")
+
+(defvar Info-keeping-history t
+ "Non-nil if Info-find-node should modify Info-history.
+This is for use only by certain internal Info routines.")
+
+(defvar Info-enable-edit nil
+ "*Non-nil means the \\[Info-edit] command in Info can edit the current node.")
+
+(defvar Info-enable-active-nodes t
+ "*Non-nil allows Info to execute Lisp code associated with nodes.
+The Lisp code is executed when the node is selected.")
+
+(defvar Info-restoring-point t
+ "*Non-nil means to restore the cursor position when re-entering a node.")
+
+(defvar Info-auto-advance 'twice
+ "*Control what SPC and DEL do when they can't scroll any further.
+If nil, they beep and remain in the current node.
+If t, they move to the next node (like Info-global-next/prev).
+If anything else, they must be pressed twice to move to the next node.")
+
+(defvar Info-directory-list (getenv "INFOPATH")
+ "List of directories to search for Info documentation files.
+Default is to use the environment variable INFOPATH if it exists,
+else to use Info-directory if it exists.")
+
+(defvar Info-suffix-list '( (".info" . nil)
+ (".Z" . "uncompress -c %s")
+ (".Y" . "unyabba")
+ (".info.Z" . "uncompress -c %s")
+ (".info.Y" . "unyabba") )
+ "List of file name suffixes and associated decoding commands.
+Each entry should be (SUFFIX . STRING); if STRING contains %s, that is
+changed to name of the file to decode, otherwise the file is given to
+the command as standard input. If STRING is nil, no decoding is done.")
+
+(defvar Info-footnote-tag "Ref"
+ "*Symbol that identifies a footnote or cross-reference.
+All \"*Note\" references will be changed to use this word instead.")
+
+(defvar Info-current-file nil
+ "Info file that Info is now looking at, or nil.")
+
+(defvar Info-current-subfile nil
+ "Info subfile that is actually in the *info* buffer now,
+or nil if current info file is not split into subfiles.")
+
+(defvar Info-current-node nil
+ "Name of node that Info is now looking at, or nil.")
+
+(defvar Info-tag-table-marker (make-marker)
+ "Marker pointing at beginning of current Info file's tag table.
+Marker points nowhere if file has no tag table.")
+
+(defvar Info-current-file-completions nil
+ "Cached completion list for current Info file.")
+
+(defvar Info-index-alternatives nil
+ "List of possible matches for last Info-index command.")
+
+(defvar Info-annotations-path '("~/.infonotes" "/usr/lib/info.notes")
+ "*Names of files that contain annotations for different Info nodes.
+By convention, the first one should reside in your personal directory.
+The last should be a world-writable \"public\" annotations file.")
+
+(defvar Info-in-cross-reference nil)
+(defvar Info-window-configuration nil)
+
+;;;###autoload
+(defun info (&optional file)
+ "Enter Info, the documentation browser.
+Optional argument FILE specifies the file to examine;
+the default is the top-level directory of Info.
+
+In interactive use, a prefix argument directs this command
+to read a file name from the minibuffer."
+ (interactive (if current-prefix-arg
+ (list (read-file-name "Info file name: " nil nil t))))
+ (Info-find-directory-list)
+ (Info-setup-x)
+ (if file
+ (Info-goto-node (concat "(" file ")"))
+ (if (get-buffer "*info*")
+ (switch-to-buffer "*info*")
+ (let ((f Info-annotations-path))
+ (while f
+ (if (file-exists-p (car f))
+ (bury-buffer (find-file-noselect (car f))))
+ (setq f (cdr f))))
+ (Info-directory))))
+
+(defun Info-find-directory-list ()
+ (if (stringp Info-directory-list)
+ (let ((path Info-directory-list)
+ list)
+ (while (> (length path) 0)
+ (let ((idx (or (string-match ":" path) (length path))))
+ (setq list (cons (substring path 0 idx) list)
+ path (substring path (min (1+ idx) (length path))))))
+ (setq Info-directory-list (nreverse list))))
+ (or Info-directory-list
+ (setq Info-directory-list (list (if (boundp 'Info-directory)
+ Info-directory
+ ".")))))
+(Info-find-directory-list)
+
+;; Go to an info node specified as separate filename and nodename.
+;; no-going-back is non-nil if recovering from an error in this function;
+;; it says do not attempt further (recursive) error recovery.
+(defun Info-find-node (filename nodename &optional no-going-back tryfile line)
+ ;; Convert filename to lower case if not found as specified.
+ ;; Expand it.
+ (if filename
+ (let (temp temp-downcase found)
+ (setq filename (substitute-in-file-name filename))
+ (let ((dirs (if (string-match "^\\./" filename)
+ ;; If specified name starts with `./'
+ ;; then just try current directory.
+ '("./")
+ Info-directory-list)))
+ ;; Search the directory list for file FILENAME.
+ (while (and dirs (not found))
+ (setq temp (expand-file-name filename (car dirs)))
+ (setq temp-downcase
+ (expand-file-name (downcase filename) (car dirs)))
+ (if (equal temp-downcase temp) (setq temp-downcase nil))
+ ;; Try several variants of specified name.
+ ;; Try downcasing, appending a suffix, or both.
+ (setq found (Info-suffixed-file temp temp-downcase))
+ (setq dirs (cdr dirs))))
+ (if found
+ (setq filename found)
+ (error "Info file %s does not exist" filename))))
+ ;; Go into info buffer.
+ (switch-to-buffer "*info*")
+ (run-hooks 'Info-startup-hook)
+ (or (eq major-mode 'Info-mode)
+ (Info-mode))
+ ;; Record the node we are leaving.
+ (if (and Info-current-file (not no-going-back))
+ (Info-history-add Info-current-file Info-current-node (point)))
+ (widen)
+ (setq Info-current-node nil
+ Info-in-cross-reference nil)
+ (unwind-protect
+ (progn
+ ;; Switch files if necessary
+ (or (null filename)
+ (equal Info-current-file filename)
+ (let ((buffer-read-only nil))
+ (setq Info-current-file nil
+ Info-current-subfile nil
+ Info-index-alternatives nil
+ Info-current-file-completions nil
+ buffer-file-name nil)
+ (erase-buffer)
+ (Info-insert-file-contents filename t)
+ ;; Add all "localdir" files in search path to "dir" file.
+ (if (string-match "^dir$" (file-name-nondirectory filename))
+ (let ((d Info-directory-list)
+ name)
+ (goto-char (point-max))
+ (if (re-search-backward "^ *\\* *Locals *: *\n" nil t)
+ (delete-region (match-beginning 0) (match-end 0))
+ (search-backward "\^L" nil t))
+ (while d
+ (setq name (expand-file-name "localdir" (car d)))
+ (if (or (file-exists-p name)
+ (file-exists-p
+ (setq name (concat name ".info"))))
+ ;; Insert menu part of the file
+ (let* ((pt (point))
+ (len (nth 1 (insert-file-contents name))))
+ (if (search-forward "* menu:" (+ pt len) t)
+ (progn
+ (forward-line 1)
+ (delete-region pt (point))))))
+ (setq d (cdr d)))
+ ;; Eliminate redundant menu entries.
+ (goto-char (point-min))
+ (while (re-search-forward "\n\\* \\([^:\n]*\\):" nil t)
+ (let ((str (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ (save-excursion
+ (if (search-forward (format "\n* %s:" str) nil t)
+ (let ((pt (- (point) 3 (length str))))
+ (forward-line 1)
+ (delete-region pt (point)))))))))
+ (set-buffer-modified-p nil)
+ (setq default-directory (file-name-directory filename))
+ ;; See whether file has a tag table. Record the location if yes.
+ (set-marker Info-tag-table-marker nil)
+ (goto-char (point-max))
+ (forward-line -8)
+ (or (equal nodename "*")
+ (not (search-forward "\^_\nEnd tag table\n" nil t))
+ (let (pos)
+ ;; We have a tag table. Find its beginning.
+ ;; Is this an indirect file?
+ (search-backward "\nTag table:\n")
+ (setq pos (point))
+ (if (save-excursion
+ (forward-line 2)
+ (looking-at "(Indirect)\n"))
+ ;; It is indirect. Copy it to another buffer
+ ;; and record that the tag table is in that buffer.
+ (save-excursion
+ (let ((buf (current-buffer)))
+ (set-buffer
+ (get-buffer-create " *info tag table*"))
+ (setq case-fold-search t)
+ (erase-buffer)
+ (insert-buffer-substring buf)
+ (set-marker Info-tag-table-marker
+ (match-end 0))))
+ (set-marker Info-tag-table-marker pos))))
+ (setq Info-current-file
+ (file-name-sans-versions buffer-file-name))))
+ (if (equal nodename "*")
+ (progn (setq Info-current-node nodename)
+ (Info-set-mode-line)
+ (goto-char (point-min)))
+ ;; Search file for a suitable node.
+ ;; First get advice from tag table if file has one.
+ ;; Also, if this is an indirect info file,
+ ;; read the proper subfile into this buffer.
+ (let ((guesspos (point-min)))
+ (if (marker-position Info-tag-table-marker)
+ (save-excursion
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char Info-tag-table-marker)
+ (if (search-forward (concat "Node: " nodename "\177") nil t)
+ (progn
+ (setq guesspos (read (current-buffer)))
+ ;; If this is an indirect file,
+ ;; determine which file really holds this node
+ ;; and read it in.
+ (if (not (eq (current-buffer) (get-buffer "*info*")))
+ (setq guesspos
+ (Info-read-subfile guesspos)))))))
+ (goto-char (max (point-min) (- guesspos 1000))))
+ ;; Now search from our advised position (or from beg of buffer)
+ ;; to find the actual node.
+ (let ((regexp (concat "Node: *" (regexp-quote nodename) " *[,\t\n]"))
+ (found t))
+ (catch 'foo
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (throw 'foo t))))
+ (setq found nil)
+ (let ((bufs (delq nil (mapcar 'get-file-buffer
+ Info-annotations-path)))
+ (pattern (concat "\"" nodename "\""))
+ (pat2 (concat "------ *File: *\\([^ ].*[^ ]\\) *Node: "
+ "*\\([^ ].*[^ ]\\) *Line: *\\([0-9]+\\)"))
+ (afile nil) anode aline)
+ (while (and bufs (not anode))
+ (save-excursion
+ (set-buffer (car bufs))
+ (goto-char (point-min))
+ (if (search-forward pattern nil t)
+ (if (re-search-backward pat2 nil t)
+ (setq afile
+ (buffer-substring (match-beginning 1)
+ (match-end 1))
+ anode
+ (buffer-substring (match-beginning 2)
+ (match-end 2))
+ aline
+ (string-to-int
+ (buffer-substring (match-beginning 3)
+ (match-end 3)))))))
+ (setq bufs (cdr bufs)))
+ (if anode
+ (Info-find-node afile anode t nil aline)
+ (if tryfile
+ (condition-case err
+ (Info-find-node nodename "Top" t)
+ (error nil)))))
+ (or Info-current-node
+ (error "No such node: %s" nodename)))
+ (if found
+ (progn
+ (Info-select-node)
+ (goto-char (point-min))
+ (if line (forward-line line)))))))
+ ;; If we did not finish finding the specified node,
+ ;; go back to the previous one.
+ (or Info-current-node no-going-back
+ (let ((hist (car Info-history)))
+ ;; The following is no longer safe with new Info-history system
+ ;; (setq Info-history (cdr Info-history))
+ (Info-goto-node (car hist) t)
+ (goto-char (nth 1 hist))))))
+
+(defun Info-history-add (file node point)
+ (if Info-keeping-history
+ (let* ((name (format "(%s)%s" (Info-file-name-only file) node))
+ (found (assoc name Info-history)))
+ (if found
+ (setq Info-history (delq found Info-history)))
+ (setq Info-history (cons (list name point
+ (and (eq (window-buffer)
+ (current-buffer))
+ (window-start)))
+ Info-history)))))
+
+(defun Info-file-name-only (file)
+ (let ((dir (file-name-directory file))
+ (p Info-directory-list))
+ (while (and p (not (equal (car p) dir)))
+ (setq p (cdr p)))
+ (if p (file-name-nondirectory file) file)))
+
+(defun Info-read-subfile (nodepos)
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (let (lastfilepos
+ lastfilename)
+ (forward-line 2)
+ (catch 'foo
+ (while (not (looking-at "\^_"))
+ (if (not (eolp))
+ (let ((beg (point))
+ thisfilepos thisfilename)
+ (search-forward ": ")
+ (setq thisfilename (buffer-substring beg (- (point) 2)))
+ (setq thisfilepos (read (current-buffer)))
+ ;; read in version 19 stops at the end of number.
+ ;; Advance to the next line.
+ ;; (forward-line 1)
+ (if (> thisfilepos nodepos)
+ (throw 'foo t))
+ (setq lastfilename thisfilename)
+ (setq lastfilepos thisfilepos))
+ (throw 'foo t))))
+ (set-buffer (get-buffer "*info*"))
+ (or (equal Info-current-subfile lastfilename)
+ (let ((buffer-read-only nil))
+ (setq buffer-file-name nil)
+ (widen)
+ (erase-buffer)
+ (Info-insert-file-contents (Info-suffixed-file lastfilename))
+ (set-buffer-modified-p nil)
+ (setq Info-current-subfile lastfilename)))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (+ (- nodepos lastfilepos) (point))))
+
+(defun Info-suffixed-file (name &optional name2)
+ (cond ((file-exists-p name)
+ name)
+ ((and name2 (file-exists-p name2))
+ name2)
+ (t
+ (let ((suff Info-suffix-list)
+ (found nil))
+ (while (and suff (not found))
+ (if (file-exists-p (concat name (car (car suff))))
+ (setq found (concat name (car (car suff))))
+ (if (and name2 (file-exists-p (concat name2 (car (car suff)))))
+ (setq found (concat name2 (car (car suff))))
+ (setq suff (cdr suff)))))
+ found))))
+
+(defun Info-insert-file-contents (file &optional visit)
+ (let ((suff Info-suffix-list))
+ (while (and suff (or (<= (length file) (length (car (car suff))))
+ (not (equal (substring file
+ (- (length (car (car suff)))))
+ (car (car suff))))))
+ (setq suff (cdr suff)))
+ (if (stringp (cdr (car suff)))
+ (let ((command (if (string-match "%s" (cdr (car suff)))
+ (format (cdr (car suff)) file)
+ (concat (cdr (car suff)) " < " file))))
+ (message "%s..." command)
+ (call-process shell-file-name nil t nil "-c" command)
+ (message "")
+ (if visit
+ (progn
+ (setq buffer-file-name file)
+ (set-buffer-modified-p nil)
+ (clear-visited-file-modtime))))
+ (insert-file-contents file visit))))
+
+(defun Info-select-node ()
+ "Select the node that point is in, after using `g *' to select whole file."
+ (interactive)
+ (widen)
+ (save-excursion
+ ;; Find beginning of node.
+ (search-backward "\n\^_")
+ (forward-line 2)
+ ;; Get nodename spelled as it is in the node.
+ (re-search-forward "Node:[ \t]*")
+ (setq Info-current-node
+ (buffer-substring (point)
+ (progn
+ (skip-chars-forward "^,\t\n")
+ (point))))
+ (Info-set-mode-line)
+ ;; Find the end of it, and narrow.
+ (beginning-of-line)
+ (let (active-expression)
+ (narrow-to-region (point)
+ (if (re-search-forward "\n[\^_\f]" nil t)
+ (prog1
+ (1- (point))
+ (if (looking-at "[\n\^_\f]*execute: ")
+ (progn
+ (goto-char (match-end 0))
+ (setq active-expression
+ (read (current-buffer))))))
+ (point-max)))
+ (or (equal Info-footnote-tag "Note")
+ (progn
+ (goto-char (point-min))
+ (let ((buffer-read-only nil)
+ (bufmod (buffer-modified-p)))
+ (while (re-search-forward "\\*Note\\([ \n]\\)" nil t)
+ (replace-match (concat "*" Info-footnote-tag "\\1")))
+ (set-buffer-modified-p bufmod))))
+ (Info-reannotate-node)
+ (run-hooks 'Info-select-hook)
+ (if Info-enable-active-nodes (eval active-expression)))))
+
+(defun Info-set-mode-line ()
+ (setq mode-line-buffer-identification
+ (concat
+ "Info: ("
+ (if Info-current-file
+ (file-name-nondirectory Info-current-file)
+ "")
+ ")"
+ (or Info-current-node ""))))
+
+;; Go to an info node specified with a filename-and-nodename string
+;; of the sort that is found in pointers in nodes.
+
+(defun Info-goto-node (nodename &optional no-going-back tryfile)
+ "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME.
+Actually, the following interpretations of NAME are tried in order:
+ (FILENAME)NODENAME
+ (FILENAME) (using Top node)
+ NODENAME (in current file)
+ TAGNAME (see below)
+ FILENAME (using Top node)
+where TAGNAME is a string that appears in quotes: \"TAGNAME\", in an
+annotation for any node of any file. (See `a' for annotations.)"
+ (interactive (list (Info-read-node-name "Goto node, file or tag: ")
+ nil t))
+ (let (filename)
+ (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
+ nodename)
+ (setq filename (if (= (match-beginning 1) (match-end 1))
+ ""
+ (substring nodename (match-beginning 2) (match-end 2)))
+ nodename (substring nodename (match-beginning 3) (match-end 3)))
+ (let ((trim (string-match "\\s *\\'" filename)))
+ (if trim (setq filename (substring filename 0 trim))))
+ (let ((trim (string-match "\\s *\\'" nodename)))
+ (if trim (setq nodename (substring nodename 0 trim))))
+ (Info-find-node (if (equal filename "") nil filename)
+ (if (equal nodename "") "Top" nodename)
+ no-going-back (and tryfile (equal filename "")))))
+
+(defun Info-restore-point (&optional always)
+ "Restore point to same location it had last time we were in this node."
+ (interactive "p")
+ (if (or Info-restoring-point always)
+ (let* ((name (format "(%s)%s"
+ (Info-file-name-only Info-current-file)
+ Info-current-node))
+ (p (assoc name Info-history)))
+ (if p (Info-restore-history-entry p)))))
+
+(defun Info-restore-history-entry (entry)
+ (goto-char (nth 1 entry))
+ (and (nth 2 entry)
+ (get-buffer-window (current-buffer))
+ (set-window-start (get-buffer-window (current-buffer))
+ (nth 2 entry))))
+
+(defun Info-read-node-name (prompt &optional default)
+ (Info-build-node-completions)
+ (let* ((completion-ignore-case t)
+ (nodename (completing-read prompt Info-current-file-completions)))
+ (if (equal nodename "")
+ (or default
+ (Info-read-node-name prompt))
+ nodename)))
+
+(defun Info-build-node-completions ()
+ (or Info-current-file-completions
+ (let ((compl nil))
+ (save-excursion
+ (save-restriction
+ (if (marker-buffer Info-tag-table-marker)
+ (progn
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char Info-tag-table-marker)
+ (while (re-search-forward "\nNode: \\(.*\\)\177" nil t)
+ (setq compl
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ compl))))
+ (widen)
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward "Node: *\\(.*\\) *[,\n\t]" beg t)
+ (setq compl
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ compl)))))))
+ (let ((bufs (delq nil (mapcar 'get-file-buffer
+ Info-annotations-path))))
+ (while bufs
+ (set-buffer (car bufs))
+ (goto-char (point-min))
+ (while (re-search-forward "\"\\(.*\\)\"" nil t)
+ (setq compl
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ compl)))
+ (setq bufs (cdr bufs)))))
+ (setq Info-current-file-completions compl))))
+
+(defvar Info-last-search nil
+ "Default regexp for Info S command to search for.")
+
+(defun Info-search (regexp)
+ "Search for REGEXP, starting from point, and select node it's found in."
+ (interactive "sSearch (regexp): ")
+ (if (equal regexp "")
+ (setq regexp Info-last-search)
+ (setq Info-last-search regexp))
+ (let ((found ()) current
+ (onode Info-current-node)
+ (ofile Info-current-file)
+ (opoint (point))
+ (osubfile Info-current-subfile))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if (null Info-current-subfile)
+ (progn (re-search-forward regexp) (setq found (point)))
+ (condition-case err
+ (progn (re-search-forward regexp) (setq found (point)))
+ (search-failed nil)))))
+ (if (not found) ;can only happen in subfile case -- else would have erred
+ (unwind-protect
+ (let ((list ()))
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_\nIndirect:")
+ (save-restriction
+ (narrow-to-region (point)
+ (progn (search-forward "\n\^_")
+ (1- (point))))
+ (goto-char (point-min))
+ (search-forward (concat "\n" osubfile ": "))
+ (beginning-of-line)
+ (while (not (eobp))
+ (re-search-forward "\\(^.*\\): [0-9]+$")
+ (goto-char (+ (match-end 1) 2))
+ (setq list (cons (cons (read (current-buffer))
+ (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ list))
+ (goto-char (1+ (match-end 0))))
+ (setq list (nreverse list)
+ current (car (car list))
+ list (cdr list)))
+ (while list
+ (message "Searching subfile %s..." (cdr (car list)))
+ (Info-read-subfile (car (car list)))
+ (setq list (cdr list))
+ (goto-char (point-min))
+ (if (re-search-forward regexp nil t)
+ (setq found (point) list ())))
+ (if found
+ (message "")
+ (signal 'search-failed (list regexp))))
+ (if (not found)
+ (progn (Info-read-subfile opoint)
+ (goto-char opoint)
+ (Info-select-node)))))
+ (widen)
+ (goto-char found)
+ (Info-select-node)
+ (or (and (equal onode Info-current-node)
+ (equal ofile Info-current-file))
+ (Info-history-add ofile onode opoint))))
+
+(defun Info-extract-pointer (name &optional errorname)
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (if (re-search-backward (concat name ":") nil t)
+ (progn
+ (goto-char (match-end 0))
+ (Info-following-node-name))
+ (if (eq errorname t)
+ nil
+ (error (concat "Node has no " (capitalize (or errorname name))))))))
+
+(defun Info-following-node-name (&optional allowedchars)
+ (skip-chars-forward " \t")
+ (buffer-substring
+ (point)
+ (progn
+ (while (looking-at (concat "[" (or allowedchars "^,\t\n") "]"))
+ (skip-chars-forward (concat (or allowedchars "^,\t\n") "("))
+ (if (looking-at "(")
+ (skip-chars-forward "^)")))
+ (skip-chars-backward " ")
+ (point))))
+
+(defun Info-next (&optional n)
+ "Go to the next node of this node.
+A positive or negative prefix argument moves by multiple nodes."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-prev (- n))
+ (while (>= (setq n (1- n)) 0)
+ (Info-goto-node (Info-extract-pointer "next")))))
+
+(defun Info-prev (&optional n)
+ "Go to the previous node of this node.
+A positive or negative prefix argument moves by multiple nodes."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-next (- n))
+ (while (>= (setq n (1- n)) 0)
+ (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous")))))
+
+(defun Info-up (&optional n)
+ "Go to the superior node of this node.
+A positive prefix argument moves up several times."
+ (interactive "p")
+ (or n (setq n 1))
+ (while (>= (setq n (1- n)) 0)
+ (Info-goto-node (Info-extract-pointer "up")))
+ (if (interactive-p) (Info-restore-point)))
+
+(defun Info-last (&optional n)
+ "Go back to the last node visited.
+With a prefix argument, go to Nth most recently visited node. History is
+circular; after oldest node, history comes back around to most recent one.
+Argument can be negative to go through the circle in the other direction.
+\(In other words, `l' is like \"undo\" and `C-u - l' is like \"redo\".)"
+ (interactive "p")
+ (or n (setq n 1))
+ (or Info-history
+ (error "This is the first Info node you looked at"))
+ (let ((len (1+ (length Info-history))))
+ (setq n (% (+ n (* len 100)) len)))
+ (if (> n 0)
+ (let ((entry (nth (1- n) Info-history)))
+ (Info-history-add Info-current-file Info-current-node (point))
+ (while (>= (setq n (1- n)) 0)
+ (setq Info-history (nconc (cdr Info-history)
+ (list (car Info-history)))))
+ (setq Info-history (cdr Info-history))
+ (let ((Info-keeping-history nil))
+ (Info-goto-node (car entry)))
+ (Info-restore-history-entry entry))))
+
+(defun Info-directory ()
+ "Go to the Info directory node."
+ (interactive)
+ (Info-find-node "dir" "top"))
+
+(defun Info-follow-reference (footnotename)
+ "Follow cross reference named NAME to the node it refers to.
+NAME may be an abbreviation of the reference name."
+ (interactive
+ (let ((completion-ignore-case t)
+ completions default (start-point (point)) str i)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward (format "\\*%s[ \n\t]*\\([^:]*\\):"
+ Info-footnote-tag)
+ nil t)
+ (setq str (buffer-substring
+ (match-beginning 1)
+ (1- (point))))
+ ;; See if this one should be the default.
+ (and (null default)
+ (< (match-beginning 0) start-point)
+ (<= start-point (point))
+ (setq default t))
+ (setq i 0)
+ (while (setq i (string-match "[ \n\t]+" str i))
+ (setq str (concat (substring str 0 i) " "
+ (substring str (match-end 0))))
+ (setq i (1+ i)))
+ ;; Record as a completion and perhaps as default.
+ (if (eq default t) (setq default str))
+ (setq completions
+ (cons (cons str nil)
+ completions))))
+ (if completions
+ (let ((item (completing-read (if default
+ (concat "Follow reference named: ("
+ default ") ")
+ "Follow reference named: ")
+ completions nil t)))
+ (if (and (string= item "") default)
+ (list default)
+ (list item)))
+ (error "No cross-references in this node"))))
+ (let (target beg i (str (concat "\\*" Info-footnote-tag " "
+ (regexp-quote footnotename))))
+ (while (setq i (string-match " " str i))
+ (setq str (concat (substring str 0 i) "\\([ \t\n]+\\)"
+ (substring str (1+ i))))
+ (setq i (+ i 10)))
+ (save-excursion
+ (goto-char (point-min))
+ (or (re-search-forward str nil t)
+ (error "No cross-reference named %s" footnotename))
+ (goto-char (match-end 1))
+ (setq target
+ (Info-extract-menu-node-name "Bad format cross reference" t)))
+ (while (setq i (string-match "[ \t\n]+" target i))
+ (setq target (concat (substring target 0 i) " "
+ (substring target (match-end 0))))
+ (setq i (+ i 1)))
+ (Info-goto-node target)
+ (setq Info-in-cross-reference t)))
+
+(defun Info-next-reference (n)
+ (interactive "p")
+ (let ((pat (format "\\*%s[ \n\t]*\\([^:]*\\):\\|^\\* .*:"
+ Info-footnote-tag))
+ (case-fold-search nil)
+ (old-pt (point)))
+ (while (< n 0)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward pat nil t)
+ (setq n (1+ n)))
+ (goto-char (point-min))
+ (if (re-search-forward "^\\* Menu:" nil t)
+ (setq n (1- n)))))
+ (while (>= (setq n (1- n)) 0)
+ (or (eobp) (forward-char 1))
+ (or (re-search-forward pat nil t)
+ (progn
+ (goto-char (point-min))
+ (or (re-search-forward pat nil t)
+ (progn
+ (goto-char old-pt)
+ (error "No cross references in this node")))))
+ (goto-char (match-beginning 0))
+ (if (looking-at "\\* Menu:")
+ (setq n (1+ n))))))
+
+(defun Info-prev-reference (n)
+ (interactive "p")
+ (Info-next-reference (- n)))
+
+(defun Info-extract-menu-node-name (&optional errmessage multi-line)
+ (skip-chars-forward " \t\n")
+ (let ((beg (point))
+ str i)
+ (skip-chars-forward "^:")
+ (forward-char 1)
+ (setq str
+ (if (looking-at ":")
+ (buffer-substring beg (1- (point)))
+ (skip-chars-forward " \t\n")
+ (Info-following-node-name (if multi-line "^.,\t" "^.,\t\n"))))
+ (while (setq i (string-match "\n" str i))
+ (aset str i ?\ ))
+ str))
+
+(defun Info-menu (menu-item)
+ "Go to node for menu item named (or abbreviated) NAME.
+Completion is allowed, and the menu item point is on is the default."
+ (interactive
+ (let ((completions '())
+ ;; If point is within a menu item, use that item as the default
+ (default nil)
+ (p (point))
+ (last nil))
+ (save-excursion
+ (goto-char (point-min))
+ (if (not (search-forward "\n* menu:" nil t))
+ (error "No menu in this node"))
+ (while (re-search-forward
+ "\n\\* \\([^:\t\n]*\\):" nil t)
+ (if (and (null default)
+ (prog1 (if last (< last p) nil)
+ (setq last (match-beginning 0)))
+ (<= p last))
+ (setq default (car (car completions))))
+ (setq completions (cons (cons (buffer-substring
+ (match-beginning 1)
+ (match-end 1))
+ (match-beginning 1))
+ completions)))
+ (if (and (null default) last
+ (< last p)
+ (<= p (progn (end-of-line) (point))))
+ (setq default (car (car completions)))))
+ (let ((item nil))
+ (while (null item)
+ (setq item (let ((completion-ignore-case t))
+ (completing-read (if default
+ (format "Menu item (default %s): "
+ default)
+ "Menu item: ")
+ completions nil t)))
+ ;; we rely on the bug (which RMS won't change for his own reasons)
+ ;; that ;; completing-read accepts an input of "" even when the
+ ;; require-match argument is true and "" is not a valid possibility
+ (if (string= item "")
+ (if default
+ (setq item default)
+ ;; ask again
+ (setq item nil))))
+ (list item))))
+ ;; there is a problem here in that if several menu items have the same
+ ;; name you can only go to the node of the first with this command.
+ (Info-goto-node (Info-extract-menu-item menu-item) nil t))
+
+(defun Info-extract-menu-item (menu-item &optional noerror)
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "\n* menu:" nil t)
+ (if (or (search-forward (concat "\n* " menu-item ":") nil t)
+ (search-forward (concat "\n* " menu-item) nil t))
+ (progn
+ (beginning-of-line)
+ (forward-char 2)
+ (Info-extract-menu-node-name))
+ (and (not noerror) (error "No such item in menu")))
+ (and (not noerror) (error "No menu in this node")))))
+
+(defun Info-extract-menu-counting (count &optional noerror noindex)
+ (save-excursion
+ (goto-char (point-min))
+ (if (and (search-forward "\n* menu:" nil t)
+ (or (not noindex)
+ (not (string-match "\\<Index\\>" Info-current-node))))
+ (if (search-forward "\n* " nil t count)
+ (progn
+ (or count
+ (while (search-forward "\n* " nil t)))
+ (Info-extract-menu-node-name))
+ (and (not noerror) (error "Too few items in menu")))
+ (and (not noerror) (error "No menu in this node")))))
+
+(defun Info-nth-menu-item (n)
+ "Go to the node of the Nth menu item."
+ (interactive "P")
+ (or n (setq n (- last-command-char ?0)))
+ (if (< n 1) (error "Index must be at least 1"))
+ (Info-goto-node (Info-extract-menu-counting n) nil t))
+
+(defun Info-last-menu-item ()
+ "Go to the node of the tenth menu item."
+ (interactive)
+ (Info-goto-node (Info-extract-menu-counting nil) nil t))
+
+(defun Info-top ()
+ "Go to the Top node of this file."
+ (interactive)
+ (Info-goto-node "Top"))
+
+(defun Info-end ()
+ "Go to the final node in this file."
+ (interactive)
+ (Info-top)
+ (let ((Info-keeping-history nil)
+ node)
+ (Info-last-menu-item)
+ (while (setq node (or (Info-extract-pointer "next" t)
+ (Info-extract-menu-counting nil t t)))
+ (Info-goto-node node))
+ (or (equal (Info-extract-pointer "up" t) "Top")
+ (let ((executing-kbd-macro "")) ; suppress messages
+ (condition-case err
+ (Info-global-next 10000)
+ (error nil))))))
+
+(defun Info-global-next (&optional n)
+ "Go to the next node in this file, traversing node structure as necessary.
+This works only if the Info file is structured as a hierarchy of nodes.
+A positive or negative prefix argument moves by multiple nodes."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-global-prev (- n))
+ (while (>= (setq n (1- n)) 0)
+ (let (node)
+ (cond ((and (string-match "^Top$" Info-current-node)
+ (setq node (Info-extract-pointer "next" t))
+ (Info-extract-menu-item node t))
+ (Info-goto-node node))
+ ((setq node (Info-extract-menu-counting 1 t t))
+ (message "Going down...")
+ (Info-goto-node node))
+ (t
+ (let ((Info-keeping-history Info-keeping-history)
+ (orignode Info-current-node)
+ (ups ""))
+ (while (not (Info-extract-pointer "next" t))
+ (if (and (setq node (Info-extract-pointer "up" t))
+ (not (equal node "Top")))
+ (progn
+ (message "Going%s..." (setq ups (concat ups " up")))
+ (Info-goto-node node)
+ (setq Info-keeping-history nil))
+ (if orignode
+ (let ((Info-keeping-history nil))
+ (Info-goto-node orignode)))
+ (error "Last node in file")))
+ (Info-next))))))))
+
+(defun Info-page-next (&optional n)
+ "Scroll forward one screenful, or go to next global node.
+A positive or negative prefix argument moves by multiple screenfuls."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-page-prev (- n))
+ (while (>= (setq n (1- n)) 0)
+ (if (pos-visible-in-window-p (point-max))
+ (progn
+ (Info-global-next)
+ (message "Node: %s" Info-current-node))
+ (scroll-up)))))
+
+(defun Info-scroll-next (arg)
+ (interactive "P")
+ (if Info-auto-advance
+ (if (and (pos-visible-in-window-p (point-max))
+ (not (eq Info-auto-advance t))
+ (not (eq last-command this-command)))
+ (message "Hit %s again to go to next node"
+ (if (= last-command-char 0)
+ "mouse button"
+ (key-description (char-to-string last-command-char))))
+ (Info-page-next)
+ (setq this-command 'Info))
+ (scroll-up arg)))
+
+(defun Info-global-prev (&optional n)
+ "Go to the previous node in this file, traversing structure as necessary.
+This works only if the Info file is structured as a hierarchy of nodes.
+A positive or negative prefix argument moves by multiple nodes."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-global-next (- n))
+ (while (>= (setq n (1- n)) 0)
+ (let ((upnode (Info-extract-pointer "up" t))
+ (prevnode (Info-extract-pointer "prev[ious]*" t)))
+ (if (or (not prevnode)
+ (equal prevnode upnode))
+ (if (string-match "^Top$" Info-current-node)
+ (error "First node in file")
+ (message "Going up...")
+ (Info-up))
+ (Info-goto-node prevnode)
+ (let ((downs "")
+ (Info-keeping-history nil)
+ node)
+ (while (setq node (Info-extract-menu-counting nil t t))
+ (message "Going%s..." (setq downs (concat downs " down")))
+ (Info-goto-node node))))))))
+
+(defun Info-page-prev (&optional n)
+ "Scroll backward one screenful, or go to previous global node.
+A positive or negative prefix argument moves by multiple screenfuls."
+ (interactive "p")
+ (or n (setq n 1))
+ (if (< n 0)
+ (Info-page-next (- n))
+ (while (>= (setq n (1- n)) 0)
+ (if (pos-visible-in-window-p (point-min))
+ (progn
+ (Info-global-prev)
+ (message "Node: %s" Info-current-node)
+ (sit-for 0)
+ ;;(scroll-up 1) ; work around bug in pos-visible-in-window-p
+ ;;(scroll-down 1)
+ (while (not (pos-visible-in-window-p (point-max)))
+ (scroll-up)))
+ (scroll-down)))))
+
+(defun Info-scroll-prev (arg)
+ (interactive "P")
+ (if Info-auto-advance
+ (if (and (pos-visible-in-window-p (point-min))
+ (not (eq Info-auto-advance t))
+ (not (eq last-command this-command)))
+ (message "Hit %s again to go to previous node"
+ (if (= last-command-char 0)
+ "mouse button"
+ (key-description (char-to-string last-command-char))))
+ (Info-page-prev)
+ (setq this-command 'Info))
+ (scroll-down arg)))
+
+(defun Info-index (topic)
+ "Look up a string in the index for this file.
+The index is defined as the first node in the top-level menu whose
+name contains the word \"Index\", plus any immediately following
+nodes whose names also contain the word \"Index\".
+If there are no exact matches to the specified topic, this chooses
+the first match which is a case-insensitive substring of a topic.
+Use the `,' command to see the other matches.
+Give a blank topic name to go to the Index node itself."
+ (interactive "sIndex topic: ")
+ (let ((orignode Info-current-node)
+ (rnode nil)
+ (pattern (format "\n\\* \\([^\n:]*%s[^\n:]*\\):[ \t]*%s"
+ (regexp-quote topic)
+ "\\([^.\n]*\\)\\.[ t]*\\([0-9]*\\)"))
+ node)
+ (Info-goto-node "Top")
+ (or (search-forward "\n* menu:" nil t)
+ (error "No index"))
+ (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
+ (error "No index"))
+ (goto-char (match-beginning 1))
+ (let ((Info-keeping-history nil))
+ (Info-goto-node (Info-extract-menu-node-name)))
+ (or (equal topic "")
+ (let ((matches nil)
+ (exact nil)
+ (Info-keeping-history nil)
+ found)
+ (while
+ (progn
+ (goto-char (point-min))
+ (while (re-search-forward pattern nil t)
+ (setq matches
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1))
+ (buffer-substring (match-beginning 2)
+ (match-end 2))
+ Info-current-node
+ (string-to-int (concat "0"
+ (buffer-substring
+ (match-beginning 3)
+ (match-end 3)))))
+ matches)))
+ (and (setq node (Info-extract-pointer "next" t))
+ (string-match "\\<Index\\>" node)))
+ (Info-goto-node node))
+ (or matches
+ (progn
+ (Info-last)
+ (error "No \"%s\" in index" topic)))
+ ;; Here it is a feature that assoc is case-sensitive.
+ (while (setq found (assoc topic matches))
+ (setq exact (cons found exact)
+ matches (delq found matches)))
+ (setq Info-index-alternatives (nconc exact (nreverse matches)))
+ (Info-index-next 0)))))
+
+(defun Info-index-next (num)
+ "Go to the next matching index item from the last `i' command."
+ (interactive "p")
+ (or Info-index-alternatives
+ (error "No previous `i' command in this file"))
+ (while (< num 0)
+ (setq num (+ num (length Info-index-alternatives))))
+ (while (> num 0)
+ (setq Info-index-alternatives
+ (nconc (cdr Info-index-alternatives)
+ (list (car Info-index-alternatives)))
+ num (1- num)))
+ (Info-goto-node (nth 1 (car Info-index-alternatives)))
+ (if (> (nth 3 (car Info-index-alternatives)) 0)
+ (forward-line (nth 3 (car Info-index-alternatives)))
+ (forward-line 3) ; don't search in headers
+ (let ((name (car (car Info-index-alternatives))))
+ (if (or (re-search-forward (format
+ "\\(Function\\|Command\\): %s\\( \\|$\\)"
+ (regexp-quote name)) nil t)
+ (search-forward (format "`%s'" name) nil t)
+ (and (string-match "\\`.*\\( (.*)\\)\\'" name)
+ (search-forward
+ (format "`%s'" (substring name 0 (match-beginning 1)))
+ nil t))
+ (search-forward name nil t))
+ (beginning-of-line)
+ (goto-char (point-min)))))
+ (message "Found \"%s\" in %s. %s"
+ (car (car Info-index-alternatives))
+ (nth 2 (car Info-index-alternatives))
+ (if (cdr Info-index-alternatives)
+ "(Press `,' for more)"
+ "(Only match)")))
+
+(defun Info-emacs-key (key)
+ "Look up an Emacs key sequence in the Emacs manual in the Info system.
+This command is designed to be used whether you are already in Info or not."
+ (interactive "kLook up key in Emacs manual: ")
+ (if (equal key "\C-g")
+ (keyboard-quit))
+ (info)
+ (Info-find-node "emacs" "Top")
+ (setq key (key-description key))
+ (let (p)
+ (if (setq p (string-match "[@{}]" key))
+ (setq key (concat (substring key 0 p) "@" (substring key p))))
+ (if (string-match "^ESC " key)
+ (setq key (concat "M-" (substring key 4))))
+ (if (string-match "^M-C-" key)
+ (setq key (concat "C-M-" (substring key 4)))))
+ (Info-index key))
+
+(defun Info-elisp-ref (func)
+ "Look up an Emacs Lisp function in the Elisp manual in the Info system.
+This command is designed to be used whether you are already in Info or not."
+ (interactive (let ((fn (function-called-at-point))
+ (enable-recursive-minibuffers t)
+ val)
+ (setq val (completing-read
+ (format "Look up Emacs Lisp function%s: "
+ (if fn
+ (format " (default %s)" fn)
+ ""))
+ obarray 'fboundp t))
+ (list (if (equal val "")
+ fn (intern val)))))
+ (info)
+ (condition-case err
+ (Info-find-node "elisp" "Top")
+ (error (Info-find-node "lispref" "Top")))
+ (Info-index (symbol-name func)))
+
+(defun Info-reannotate-node ()
+ (let ((bufs (delq nil (mapcar 'get-file-buffer Info-annotations-path))))
+ (if bufs
+ (let ((ibuf (current-buffer))
+ (file (regexp-quote
+ (file-name-nondirectory Info-current-file)))
+ (node (regexp-quote Info-current-node))
+ (savept (point)))
+ (goto-char (point-min))
+ (if (search-forward "\n------ NOTE:\n" nil t)
+ (let ((buffer-read-only nil)
+ (bufmod (buffer-modified-p))
+ top)
+ (setq savept (copy-marker savept))
+ (goto-char (point-min))
+ (while (search-forward "\n------ NOTE:" nil t)
+ (setq top (1+ (match-beginning 0)))
+ (if (search-forward "\n------\n" nil t)
+ (delete-region top (point)))
+ (backward-char 1))
+ (set-buffer-modified-p bufmod)))
+ (save-excursion
+ (while bufs
+ (set-buffer (car bufs))
+ (goto-char (point-min))
+ (while (re-search-forward
+ (format
+ "------ *File: *%s *Node: *%s *Line: *\\([0-9]+\\) *\n"
+ file node)
+ nil t)
+ (let ((line (string-to-int
+ (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ (top (point))
+ bot)
+ (search-forward "\n------\n" nil t)
+ (setq bot (point))
+ (save-excursion
+ (set-buffer ibuf)
+ (if (integerp savept) (setq savept (copy-marker savept)))
+ (if (= line 0)
+ (goto-char (point-max))
+ (goto-char (point-min))
+ (forward-line line))
+ (let ((buffer-read-only nil)
+ (bufmod (buffer-modified-p)))
+ (insert "------ NOTE:\n")
+ (insert-buffer-substring (car bufs) top bot)
+ (set-buffer-modified-p bufmod)))))
+ (setq bufs (cdr bufs))))
+ (goto-char savept)))))
+
+(defvar Info-annotate-map nil
+ "Local keymap used within `a' command of Info.")
+(if Info-annotate-map
+ nil
+ ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map))
+ (setq Info-annotate-map (copy-keymap text-mode-map))
+ (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate))
+
+(defun Info-annotate-mode ()
+ "Major mode for adding an annotation to an Info node.
+Like text mode with the addition of Info-cease-annotate
+which returns to Info mode for browsing.
+\\{Info-annotate-map}")
+
+(defun Info-annotate (arg)
+ "Add a personal annotation to the current Info node.
+Only you will be able to see this annotation.
+Annotations are stored in the file ~/.infonotes by default.
+If point is inside an existing annotation, edit that annotation.
+A prefix argument specifies which annotations file (from
+Info-annotations-path) is to be edited; default is 1."
+ (interactive "p")
+ (setq arg (1- arg))
+ (if (or (< arg 0) (not (nth arg Info-annotations-path)))
+ (if (= arg 0)
+ (setq Info-annotations-path
+ (list (read-file-name
+ "Annotations file: " "~/" "~/.infonotes")))
+ (error "File number must be in the range from 1 to %d"
+ (length Info-annotations-path))))
+ (let ((which nil)
+ where pt)
+ (if (and (save-excursion
+ (goto-char (min (point-max) (+ (point) 13)))
+ (and (search-backward "------ NOTE:\n" nil t)
+ (setq pt (match-end 0))
+ (search-forward "\n------\n" nil t)))
+ (< (point) (match-end 0)))
+ (setq which (format "File: *%s *Node: *%s *Line:.*\n%s"
+ (regexp-quote
+ (file-name-nondirectory Info-current-file))
+ (regexp-quote Info-current-node)
+ (regexp-quote
+ (buffer-substring pt (match-beginning 0))))
+ where (max (- (point) pt) 0)))
+ (let ((file (file-name-nondirectory Info-current-file))
+ (node Info-current-node)
+ (line (if (looking-at "[ \n]*\\'") 0
+ (count-lines (point-min) (point)))))
+ (or which
+ (let ((buffer-read-only nil)
+ (bufmod (buffer-modified-p))
+ top)
+ (beginning-of-line)
+ (if (bobp) (goto-char (point-max)))
+ (insert "------ NOTE:\n------\n")
+ (backward-char 20)
+ (set-buffer-modified-p bufmod)))
+ ;; (setq Info-window-start (window-start))
+ (setq Info-window-configuration (current-window-configuration))
+ (pop-to-buffer (find-file-noselect (nth arg Info-annotations-path)))
+ (use-local-map Info-annotate-map)
+ (setq major-mode 'Info-annotate-mode)
+ (setq mode-name "Info Annotate")
+ (if which
+ (if (save-excursion
+ (goto-char (point-min))
+ (re-search-forward which nil t))
+ (progn
+ (goto-char (match-beginning 0))
+ (forward-line 1)
+ (forward-char where)))
+ (let ((bufmod (buffer-modified-p)))
+ (goto-char (point-max))
+ (insert (format "\n------ File: %s Node: %s Line: %d\n"
+ file node line))
+ (setq pt (point))
+ (insert "\n------\n"
+ "\nPress C-c C-c to save and return to Info.\n")
+ (goto-char pt)
+ (set-buffer-modified-p bufmod))))))
+
+(defun Info-cease-annotate ()
+ (interactive)
+ (let ((bufmod (buffer-modified-p)))
+ (while (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "\n\n?Press .* to save and return to Info.\n"
+ nil t))
+ (delete-region (1+ (match-beginning 0)) (match-end 0)))
+ (while (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "\n------ File:.*Node:.*Line:.*\n+------\n"
+ nil t))
+ (delete-region (match-beginning 0) (match-end 0)))
+ (set-buffer-modified-p bufmod))
+ (save-buffer)
+ (fundamental-mode)
+ (bury-buffer)
+ (or (one-window-p) (delete-window))
+ (info)
+ (setq Info-current-file-completions nil)
+ (set-window-configuration Info-window-configuration)
+ (Info-reannotate-node))
+
+(defun Info-exit ()
+ "Exit Info by selecting some other buffer."
+ (interactive)
+ (switch-to-buffer (prog1 (other-buffer (current-buffer))
+ (bury-buffer (current-buffer)))))
+
+(defun Info-undefined ()
+ "Make command be undefined in Info."
+ (interactive)
+ (ding))
+
+(defun Info-help ()
+ "Enter the Info tutorial."
+ (interactive)
+ (delete-other-windows)
+ (Info-find-node "info"
+ (if (< (window-height) 23)
+ "Help-Small-Screen"
+ "Help")))
+
+(defun Info-summary ()
+ "Display a brief summary of all Info commands."
+ (interactive)
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (erase-buffer)
+ (insert (documentation 'Info-mode))
+ (goto-char (point-min))
+ (let (ch flag)
+ (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
+ (message (if flag "Type Space to see more"
+ "Type Space to return to Info"))
+ (if (/= ?\ (setq ch (read-char)))
+ (progn (setq unread-command-char ch) nil)
+ flag))
+ (scroll-up)))
+ (bury-buffer "*Help*")))
+
+(defun Info-get-token (pos start all &optional errorstring)
+ "Return the token around POS,
+POS must be somewhere inside the token
+START is a regular expression which will match the
+ beginning of the tokens delimited string
+ALL is a regular expression with a single
+ parenthized subpattern which is the token to be
+ returned. E.g. '{\(.*\)}' would return any string
+ enclosed in braces around POS.
+SIG optional fourth argument, controls action on no match
+ nil: return nil
+ t: beep
+ a string: signal an error, using that string."
+ (save-excursion
+ (goto-char pos)
+ (re-search-backward start (max (point-min) (- pos 200)) 'yes)
+ (while (and (re-search-forward all (min (point-max) (+ pos 200)) 'yes)
+ (not (and (<= (match-beginning 0) pos)
+ (> (match-end 0) pos)))))
+ (if (and (<= (match-beginning 0) pos)
+ (> (match-end 0) pos)
+ (match-beginning 1))
+ (buffer-substring (match-beginning 1) (match-end 1))
+ (cond ((null errorstring)
+ nil)
+ ((eq errorstring t)
+ (beep)
+ nil)
+ (t
+ (error "No %s around position %d" errorstring pos))))))
+
+(defun Info-follow-clicked-node (event)
+ "Follow a node reference near clicked point. Like M, F, N, P or U command.
+At end of the node's text, moves to the next node."
+ (interactive "@e")
+ (let* ((relative-coordinates (coordinates-in-window-p (car event)
+ (selected-window)))
+ (rel-x (car relative-coordinates))
+ (rel-y (car (cdr relative-coordinates)))
+ (point (save-excursion
+ (move-to-window-line rel-y)
+ (move-to-column (+ rel-x (current-column)))
+ (point))))
+ (Info-follow-nearest-node (max point (1+ (point-min))))))
+
+(defun Info-follow-nearest-node (point)
+ "Follow a node reference near point. Like M, F, N, P or U command.
+At end of the node's text, moves to the next node."
+ (interactive "d")
+ (let (node)
+ (cond
+ ((= point (point-min))) ; don't trigger on accidental RET.
+ ((setq node (Info-get-token point
+ (format "\\*%s[ \n]" Info-footnote-tag)
+ (format "\\*%s[ \n]\\([^:]*\\):"
+ Info-footnote-tag)))
+ (message "Following cross-reference %s..." node)
+ (Info-follow-reference node))
+ ((setq node (Info-get-token point "\\* " "\\* \\([^:]*\\)::"))
+ (message "Selecting menu item %s..." node)
+ (Info-goto-node node))
+ ((setq node (Info-get-token point "\\* " "\\* \\([^:]*\\):"))
+ (message "Selecting menu item %s..." node)
+ (Info-menu node))
+ ((setq node (Info-get-token point "Up: " "Up: \\([^,\n\t]*\\)"))
+ (message "Going up...")
+ (Info-goto-node node))
+ ((setq node (Info-get-token point "Next: " "Next: \\([^,\n\t]*\\)"))
+ (message "Next node...")
+ (Info-goto-node node))
+ ((setq node (Info-get-token point "File: " "File: \\([^,\n\t]*\\)"))
+ (message "Top node...")
+ (Info-goto-node "Top"))
+ ((setq node (Info-get-token point "Prev[ious]*: "
+ "Prev[ious]*: \\([^,\n\t]*\\)"))
+ (message "Previous node...")
+ (Info-goto-node node))
+ ((save-excursion (goto-char point) (looking-at "[ \n]*\\'"))
+ (if Info-in-cross-reference
+ (progn
+ (message "Back to last node...")
+ (Info-last))
+ (message "Next node...")
+ (Info-global-next))))
+ ))
+
+;;; Provide Emacs 18 support for mouse clicks.
+(defvar Info-prev-x-right-click nil)
+(defvar Info-prev-x-middle-click nil)
+(defvar Info-prev-x-left-click nil)
+(defvar Info-prev-x-s-right-click nil)
+(defvar Info-prev-x-s-middle-click nil)
+(defvar Info-prev-x-s-left-click nil)
+(defun Info-setup-x ()
+ (and (eq window-system 'x)
+ (not Info-prev-x-left-click)
+ Info-mouse-support
+ (progn
+ (setq Info-prev-x-right-click (aref mouse-map 0)
+ Info-prev-x-middle-click (aref mouse-map 1)
+ Info-prev-x-left-click (aref mouse-map 2)
+ Info-prev-x-s-right-click (aref mouse-map 16)
+ Info-prev-x-s-middle-click (aref mouse-map 17)
+ Info-prev-x-s-left-click (aref mouse-map 18))
+ (aset mouse-map 0 'Info-x-right-click)
+ (aset mouse-map 1 'Info-x-middle-click)
+ (aset mouse-map 2 'Info-x-left-click)
+ (aset mouse-map 16 'Info-x-s-right-click)
+ (aset mouse-map 17 'Info-x-s-middle-click)
+ (aset mouse-map 18 'Info-x-s-left-click))))
+
+(defun Info-x-left-click (arg)
+ "Handle a left-button mouse click in Info window."
+ (Info-handle-click '(condition-case err (Info-scroll-next nil) (error nil))
+ arg Info-prev-x-left-click))
+
+(defun Info-x-right-click (arg)
+ "Handle a right-button mouse click in Info window."
+ (Info-handle-click '(condition-case err (Info-scroll-prev nil) (error nil))
+ arg Info-prev-x-right-click))
+
+(defun Info-x-middle-click (arg)
+ "Handle a middle-button mouse click in Info window."
+ (Info-handle-click '(Info-follow-clicked-node (list arg))
+ arg Info-prev-x-middle-click))
+
+(defun Info-x-s-left-click (arg)
+ "Handle a shift-left-button mouse click in Info window."
+ (Info-handle-click '(Info-global-next) arg Info-prev-x-s-left-click))
+
+(defun Info-x-s-right-click (arg)
+ "Handle a shift-right-button mouse click in Info window."
+ (Info-handle-click '(Info-global-prev) arg Info-prev-x-s-right-click))
+
+(defun Info-x-s-middle-click (arg)
+ "Handle a shift-middle-button mouse click in Info window."
+ (Info-handle-click '(Info-last) arg Info-prev-x-s-middle-click))
+
+(defun Info-handle-click (form arg prev)
+ (if (and (get-buffer-window "*info*")
+ (coordinates-in-window-p arg (get-buffer-window "*info*")))
+ (let ((win (selected-window)))
+ (unwind-protect
+ (progn
+ (select-window (get-buffer-window "*info*"))
+ (eval form))
+ (and (window-point win)
+ (select-window win))))
+ (funcall prev arg)))
+
+(defun x-mouse-ignore (arg)
+ "Don't do anything."
+ ;; Added the following line to support Info-auto-advance mode.
+ (setq this-command last-command))
+
+(defvar Info-mode-map nil
+ "Keymap containing Info commands.")
+(if Info-mode-map
+ nil
+ (setq Info-mode-map (make-keymap))
+ (suppress-keymap Info-mode-map)
+ (define-key Info-mode-map "." 'beginning-of-buffer)
+ (define-key Info-mode-map " " 'Info-scroll-next)
+ (define-key Info-mode-map "1" 'Info-nth-menu-item)
+ (define-key Info-mode-map "2" 'Info-nth-menu-item)
+ (define-key Info-mode-map "3" 'Info-nth-menu-item)
+ (define-key Info-mode-map "4" 'Info-nth-menu-item)
+ (define-key Info-mode-map "5" 'Info-nth-menu-item)
+ (define-key Info-mode-map "6" 'Info-nth-menu-item)
+ (define-key Info-mode-map "7" 'Info-nth-menu-item)
+ (define-key Info-mode-map "8" 'Info-nth-menu-item)
+ (define-key Info-mode-map "9" 'Info-nth-menu-item)
+ (define-key Info-mode-map "0" 'Info-last-menu-item)
+ (define-key Info-mode-map "?" 'Info-summary)
+ (define-key Info-mode-map "a" 'Info-annotate)
+ (define-key Info-mode-map "b" 'beginning-of-buffer)
+ (define-key Info-mode-map "d" 'Info-directory)
+ (define-key Info-mode-map "e" 'Info-edit)
+ (define-key Info-mode-map "f" 'Info-follow-reference)
+ (define-key Info-mode-map "g" 'Info-goto-node)
+ (define-key Info-mode-map "h" 'Info-help)
+ (define-key Info-mode-map "i" 'Info-index)
+ (define-key Info-mode-map "k" 'Info-emacs-key)
+ (define-key Info-mode-map "l" 'Info-last)
+ (define-key Info-mode-map "m" 'Info-menu)
+ (define-key Info-mode-map "n" 'Info-next)
+ (define-key Info-mode-map "p" 'Info-prev)
+ (define-key Info-mode-map "q" 'Info-exit)
+ (define-key Info-mode-map "r" 'Info-follow-reference)
+ (define-key Info-mode-map "s" 'Info-search)
+ (define-key Info-mode-map "t" 'Info-top)
+ (define-key Info-mode-map "u" 'Info-up)
+ (define-key Info-mode-map "<" 'Info-top)
+ (define-key Info-mode-map ">" 'Info-end)
+ (define-key Info-mode-map "[" 'Info-global-prev)
+ (define-key Info-mode-map "]" 'Info-global-next)
+ (define-key Info-mode-map "{" 'Info-page-prev)
+ (define-key Info-mode-map "}" 'Info-page-next)
+ (define-key Info-mode-map "=" 'Info-restore-point)
+ (define-key Info-mode-map "!" 'Info-select-node)
+ (define-key Info-mode-map "@" 'Info-follow-nearest-node)
+ (define-key Info-mode-map "," 'Info-index-next)
+ (define-key Info-mode-map "*" 'Info-elisp-ref)
+ (define-key Info-mode-map "\t" 'Info-next-reference)
+ (define-key Info-mode-map "\e\t" 'Info-prev-reference)
+ (define-key Info-mode-map "\r" 'Info-follow-nearest-node)
+ (define-key Info-mode-map "\177" 'Info-scroll-prev))
+
+(or (lookup-key help-map "\C-k")
+ (define-key help-map "\C-k" 'Info-emacs-key))
+
+(or (lookup-key help-map "\C-f")
+ (define-key help-map "\C-f" 'Info-elisp-ref))
+
+(let ((help (symbol-function 'help-for-help))
+ (doc (documentation 'help-for-help)))
+ (and (consp help) (eq (car help) 'lambda)
+ (not (string-match "C-k" doc))
+ (setq doc (concat
+ doc
+ "\n\nC-k Info-emacs-key. Look up a key in Emacs manual."
+ "\nC-f Info-elisp-ref."
+ " Look up a function in Emacs Lisp manual."))
+ (fset 'help-for-help
+ (cons 'lambda (cons (nth 1 help) (cons doc (nthcdr 2 help)))))))
+
+
+;;; The following stuff is for Emacs 19 only---it's ignored in Emacs 18.
+(defvar Info-mode-mouse-map nil
+ "Mouse map for use with Info mode.")
+
+(if Info-mode-mouse-map
+ nil
+ (if (or (not (boundp 'global-mouse-map))
+ (null (cdr global-mouse-map)))
+ nil
+ (setq Info-mode-mouse-map (make-sparse-keymap))
+ (define-key Info-mode-mouse-map mouse-button-middle
+ 'Info-follow-clicked-node)
+ (define-key Info-mode-mouse-map mouse-button-left 'mouse-scroll-up-full)
+ (define-key Info-mode-mouse-map mouse-button-right
+ 'mouse-scroll-down-full)))
+
+;; Info mode is suitable only for specially formatted data.
+(put 'info-mode 'mode-class 'special)
+
+(defun Info-mode ()
+ "Info mode is for browsing through the Info documentation tree.
+Documentation in Info is divided into \"nodes\", each of which
+discusses one topic and contains references to other nodes
+which discuss related topics. Info has commands to follow
+the references and show you other nodes.
+
+h Invoke the Info tutorial.
+q Quit Info: return to previously selected file or buffer.
+
+Selecting other nodes:
+n Move to the \"next\" node of this node.
+p Move to the \"previous\" node of this node.
+m Pick menu item specified by name (or abbreviation).
+1-9, 0 Pick first..ninth, last item in node's menu.
+ Menu items select nodes that are \"subsections\" of this node.
+u Move \"up\" from this node (i.e., from a subsection to a section).
+f or r Follow a cross reference by name (or abbrev). Type `l' to get back.
+RET Follow cross reference or menu item indicated by cursor.
+i Look up a topic in this file's Index and move to that node.
+, (comma) Move to the next match from a previous `i' command.
+l (letter L) Move back to the last node you were in.
+
+Moving within a node:
+Space Scroll forward a full screen. DEL Scroll backward.
+b Go to beginning of node. Meta-> Go to end of node.
+TAB Go to next cross-reference. Meta-TAB Go to previous ref.
+
+Mouse commands: Shifted mouse commands:
+Middle Follow reference (RET). S-Middle Back to last node (`l').
+Left Next page or node (Space). S-Left Next node (`]').
+Right Prev page or node (DEL). S-Right Prev node (`[').
+
+Advanced commands:
+g Move to node, file, or annotation tag specified by name.
+ Examples: `g Rectangles' `g (Emacs)Rectangles' `g Emacs'.
+k Look up a key sequence in Emacs manual (also C-h C-k at any time).
+* Look up a function name in Emacs Lisp manual (also C-h C-f).
+d Go to the main directory of Info files.
+< or t Go to Top (first) node of this file.
+> Go to last node in this file.
+\[ Go to previous node, treating file as one linear document.
+\] Go to next node, treating file as one linear document.
+{ Scroll backward, or go to previous node if at top.
+} Scroll forward, or go to next node if at bottom.
+= Restore cursor position from last time in this node.
+a Add a private note (annotation) to the current node.
+s Search this Info file for a node containing the specified regexp.
+e Edit the contents of the current node."
+ (kill-all-local-variables)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (use-local-map Info-mode-map)
+ (set-syntax-table text-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (setq case-fold-search t)
+ (setq buffer-read-only t)
+ (setq buffer-mouse-map Info-mode-mouse-map)
+ (make-local-variable 'Info-current-file)
+ (make-local-variable 'Info-current-subfile)
+ (make-local-variable 'Info-current-node)
+ (make-local-variable 'Info-tag-table-marker)
+ (make-local-variable 'Info-current-file-completions)
+ (make-local-variable 'Info-index-alternatives)
+ (make-local-variable 'Info-history)
+ (run-hooks 'Info-mode-hook)
+ (Info-set-mode-line))
+
+(defvar Info-edit-map nil
+ "Local keymap used within `e' command of Info.")
+(if Info-edit-map
+ nil
+ ;; (setq Info-edit-map (nconc (make-sparse-keymap) text-mode-map))
+ (setq Info-edit-map (copy-keymap text-mode-map))
+ (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
+
+;; Info-edit mode is suitable only for specially formatted data.
+(put 'info-edit-mode 'mode-class 'special)
+
+(defun Info-edit-mode ()
+ "Major mode for editing the contents of an Info node.
+Like text mode with the addition of Info-cease-edit
+which returns to Info mode for browsing.
+\\{Info-edit-map}"
+ )
+
+(defun Info-edit ()
+ "Edit the contents of this Info node.
+Allowed only if variable Info-enable-edit is non-nil."
+ (interactive)
+ (or Info-enable-edit
+ (error "Editing info nodes is not enabled"))
+ (use-local-map Info-edit-map)
+ (setq major-mode 'Info-edit-mode)
+ (setq mode-name "Info Edit")
+ (kill-local-variable 'mode-line-buffer-identification)
+ (setq buffer-read-only nil)
+ ;; Make mode line update.
+ (set-buffer-modified-p (buffer-modified-p))
+ (message (substitute-command-keys
+ "Editing: Type \\[Info-cease-edit] to return to info")))
+
+(defun Info-cease-edit ()
+ "Finish editing Info node; switch back to Info proper."
+ (interactive)
+ ;; Do this first, so nothing has changed if user C-g's at query.
+ (and (buffer-modified-p)
+ (y-or-n-p "Save the file? ")
+ (save-buffer))
+ (use-local-map Info-mode-map)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (Info-set-mode-line)
+ (setq buffer-read-only t)
+ ;; Make mode line update.
+ (set-buffer-modified-p (buffer-modified-p))
+ (and (marker-position Info-tag-table-marker)
+ (buffer-modified-p)
+ (message "Tags may have changed. Use Info-tagify if necessary")))
+
+(run-hooks 'Info-load-hook)
+
+;;; End.
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/linebreaks.texi b/web/glasgow/lit2x-0.16/literate/info-utils/linebreaks.texi
new file mode 100644
index 0000000000..df18fdb5c8
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/linebreaks.texi
@@ -0,0 +1,18 @@
+@setfilename linebreaks.info
+
+@node Top, , , (dir)
+@comment node, next, previous, up
+@srcfilename handbook.lit
+@srclineno 1
+
+@c see the bug if paragraph-indent is run at zero
+
+The one command that needs more explanation is the @w{@samp{m}} command, which is
+short for "menu", becuase you have to specify which subsection you want to
+visit.
+
+An example of a menu appears just below. It gives the names and title
+of the subsections of this section. These give further information
+about using the index to find your way around, using cross-references,
+printing parts of the handbook, and so on. You can use the @w{@samp{m}}
+command to read them.
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.c b/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.c
new file mode 100644
index 0000000000..b595ee0432
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.c
@@ -0,0 +1,7522 @@
+/* Makeinfo -- convert texinfo format files into info files.
+
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+ This file is part of GNU Info.
+
+ Makeinfo is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor accepts
+ responsibility to anyone for the consequences of using it or for
+ whether it serves any particular purpose or works at all, unless he
+ says so in writing. Refer to the GNU Emacs General Public License
+ for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ Makeinfo, but only under the conditions described in the GNU Emacs
+ General Public License. A copy of this license is supposed to
+ have been given to you along with GNU Emacs so you can know your
+ rights and responsibilities. It should be in a file named COPYING.
+ Among other things, the copyright notice and this notice must be
+ preserved on all copies. */
+
+/* This is Makeinfo version 1.47. If you change the version number of
+ Makeinfo, please change it here and at the lines reading:
+
+ int major_version = 1;
+ int minor_version = 47;
+
+ in the code below. */
+
+/* You can change some of the behaviour of Makeinfo by changing the
+ following defines: */
+
+/* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
+ appear within an @table, @ftable, or @itemize environment to have
+ standard paragraph indentation. Without this, such paragraphs have
+ no starting indentation. */
+/* #define INDENT_PARAGRAPHS_IN_TABLE */
+
+/* Define DEFAULT_INDENTATION_INCREMENT as an integer which is the amount
+ that @example should increase indentation by. This increment is used
+ for all insertions which indent the enclosed text. */
+#define DEFAULT_INDENTATION_INCREMENT 5
+
+/* Define PARAGRAPH_START_INDENT to be the amount of indentation that
+ the first lines of paragraphs receive by default, where no other
+ value has been specified. Users can change this value on the command
+ line, with the +paragraph-indent option, or within the texinfo file,
+ with the @paragraphindent command. */
+#define PARAGRAPH_START_INDENT 0 /* partain changed from 3 */
+
+/* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
+ wish to appear between paragraphs. A value of 1 creates a single blank
+ line between paragraphs. Paragraphs are defined by 2 or more consecutive
+ newlines in the input file (i.e., one or more blank lines). */
+#define DEFAULT_PARAGRAPH_SPACING 1
+
+/* **************************************************************** */
+/* */
+/* Include File Declarations */
+/* */
+/* **************************************************************** */
+
+/* Indent #pragma so that older Cpp's don't try to parse it. */
+#if defined (_AIX)
+ # pragma alloca
+#endif /* _AIX */
+
+/* partain: to go w/ "make world" */
+#if defined(SYSV)
+#define USG 1
+#endif
+/* end partain */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <errno.h>
+#include "getopt.h"
+
+#if defined (VMS)
+# include <perror.h>
+#endif
+
+#if defined (USG) || defined (VMS)
+# include <string.h>
+# include <time.h>
+#else /* !USG && !VMS */
+# include <strings.h>
+# include <sys/time.h>
+#endif /* !USG && !VMS */
+
+#include <fcntl.h>
+#include <sys/file.h>
+
+#if defined (USG) || defined (hpux)
+#define bcopy(source, dest, count) memcpy (dest, source, count)
+char *index (s, c) char *s; { char *strchr (); return strchr (s, c); }
+char *rindex (s, c) char *s; { char *strrchr (); return (strrchr (s, c)); }
+#endif /* USG || hpux */
+
+#if defined (__GNUC__)
+# define alloca __builtin_alloca
+#else
+# if defined (sparc)
+# include <alloca.h>
+# else
+# if !defined (_AIX)
+extern char *alloca ();
+# endif /* _AIX */
+# endif /* !sparc */
+#endif /* !__GNUC__ */
+
+/* Forward declarations. */
+void *xmalloc (), *xrealloc ();
+
+/* Non-zero means that we are currently hacking the insides of an
+ insertion which would use a fixed width font. */
+static int in_fixed_width_font = 0;
+
+/* Non-zero means that start_paragraph () MUST be called before we pay
+ any attention to close_paragraph () calls. */
+int must_start_paragraph = 0;
+
+/* Some systems don't declare this function in pwd.h. */
+struct passwd *getpwnam ();
+
+
+/* **************************************************************** */
+/* */
+/* Global Defines */
+/* */
+/* **************************************************************** */
+
+/* Error levels */
+#define NO_ERROR 0
+#define SYNTAX 2
+#define FATAL 4
+
+/* How to allocate permanent storage for STRING. */
+#define savestring(x) \
+ ((char *)strcpy ((char *)xmalloc (1 + ((x) ? strlen (x) : 0)), \
+ (x) ? (x) : ""))
+
+/* C's standard macros don't check to make sure that the characters being
+ changed are within range. So I have to check explicitly. */
+
+/* GNU Library doesn't have toupper(). Until GNU gets this fixed, I will
+ have to do it. */
+#ifndef toupper
+#define toupper(c) ((c) - 32)
+#endif
+
+#define coerce_to_upper(c) ((islower(c) ? toupper(c) : (c)))
+#define coerce_to_lower(c) ((isupper(c) ? tolower(c) : (c)))
+
+#define control_character_bit 0x40 /* %01000000, must be off. */
+#define meta_character_bit 0x080/* %10000000, must be on. */
+#define CTL(c) ((c) & (~control_character_bit))
+#define UNCTL(c) coerce_to_upper(((c)|control_character_bit))
+#define META(c) ((c) | (meta_character_bit))
+#define UNMETA(c) ((c) & (~meta_character_bit))
+
+#define whitespace(c) (((c) == '\t') || ((c) == ' '))
+#define sentence_ender(c) ((c) == '.' || (c) == '?' || (c) == '!')
+#define cr_or_whitespace(c) (((c) == '\t') || ((c) == ' ') || ((c) == '\n'))
+
+#ifndef isletter
+#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#endif
+
+#ifndef isupper
+#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
+#endif
+
+#ifndef isdigit
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#define member(c, s) (index (s, c) != NULL)
+
+#define COMMAND_PREFIX '@'
+
+/* Stuff for splitting large files. */
+#define SPLIT_SIZE_THRESHOLD 70000 /* What's good enough for Stallman... */
+#define DEFAULT_SPLIT_SIZE 50000/* Is probably good enough for me. */
+/* partain: orig
+int splitting = 1; /? Always true for now. ?/
+*/
+int splitting = 0; /* Always false for now. */
+
+typedef int FUNCTION (); /* So I can say FUNCTION *foo; */
+
+
+/* **************************************************************** */
+/* */
+/* Global Variables */
+/* */
+/* **************************************************************** */
+
+/* Global pointer to argv[0]. */
+char *progname;
+
+/* The current input file state. */
+char *input_filename;
+#ifdef TRACK_SRCFILE
+char *src_filename;
+int src_lineno;
+#endif /* TRACK_SRCFILE */
+char *input_text;
+int size_of_input_text;
+int input_text_offset;
+int line_number;
+
+#define curchar() input_text[input_text_offset]
+
+#define command_char(c) ((!whitespace(c)) && \
+ ((c) != '\n') && \
+ ((c) != '{') && \
+ ((c) != '}') && \
+ ((c) != '='))
+
+#define skip_whitespace() while (input_text_offset != size_of_input_text \
+ && whitespace(curchar()))\
+ input_text_offset++
+
+/* Return non-zero if STRING is the text at input_text + input_text_offset,
+ else zero. */
+#define looking_at(string) \
+ (strncmp (input_text + input_text_offset, string, strlen (string)) == 0)
+
+/* And writing to the output. */
+
+/* The output file name. */
+char *output_filename = (char *)NULL;
+char *pretty_output_filename;
+
+/* Name of the output file that the user elected to pass on the command line.
+ Such a name overrides any name found with the @setfilename command. */
+char *command_output_filename = (char *)NULL;
+
+/* A colon separated list of directories to search for files included
+ with @include. This can be controlled with the `-I' option to makeinfo. */
+char *include_files_path = (char *)NULL;
+
+/* Current output stream. */
+FILE *output_stream;
+
+/* Position in the output file. */
+int output_position;
+
+/* Output paragraph buffer. */
+unsigned char *output_paragraph;
+
+/* Offset into OUTPUT_PARAGRAPH. */
+int output_paragraph_offset;
+
+/* The output paragraph "cursor" horizontal position. */
+int output_column = 0;
+
+/* Non-zero means output_paragraph contains text. */
+int paragraph_is_open = 0;
+
+#define INITIAL_PARAGRAPH_SPACE 5000
+int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
+
+/* Filling.. */
+/* Non-zero indicates that filling will take place on long lines. */
+int filling_enabled = 1;
+
+/* Non-zero means that words are not to be split, even in long lines. This
+ gets changed for cm_w (). */
+int non_splitting_words = 0;
+
+/* Non-zero indicates that filling a line also indents the new line. */
+int indented_fill = 0;
+
+/* The column at which long lines are broken. */
+int fill_column = 72;
+
+/* The amount of indentation to apply at the start of each line. */
+int current_indent = 0;
+
+/* The amount of indentation to add at the starts of paragraphs.
+ 0 means don't change existing indentation at paragraph starts.
+ > 0 is amount to indent new paragraphs by.
+ < 0 means indent to column zero by removing indentation if necessary.
+
+ This is normally zero, but some people prefer paragraph starts to be
+ somewhat more indented than paragraph bodies. A pretty value for
+ this is 3. */
+int paragraph_start_indent = PARAGRAPH_START_INDENT;
+
+/* Non-zero means that the use of paragraph_start_indent is inhibited.
+ @example uses this to line up the left columns of the example text.
+ A negative value for this variable is incremented each time it is used.
+ @noindent uses this to inhibit indentation for a single paragraph. */
+int inhibit_paragraph_indentation = 0;
+
+/* Indentation that is pending insertion. We have this for hacking lines
+ which look blank, but contain whitespace. We want to treat those as
+ blank lines. */
+int pending_indent = 0;
+
+/* The amount that indentation increases/decreases by. */
+int default_indentation_increment = DEFAULT_INDENTATION_INCREMENT;
+
+/* Non-zero indicates that indentation is temporarily turned off. */
+int no_indent = 1;
+
+/* Non-zero means forcing output text to be flushright. */
+int force_flush_right = 0;
+
+/* Non-zero means that the footnote style for this document was set on
+ the command line, which overrides any other settings. */
+int footnote_style_preset = 0;
+
+/* Non-zero means that we automatically number footnotes that have no
+ specified marker. */
+int number_footnotes = 1;
+
+/* The current footnote number in this node. Each time a new node is
+ started this is reset to 1. */
+int current_footnote_number = 1;
+
+/* Command name in the process of being hacked. */
+char *command;
+
+/* The index in our internal command table of the currently
+ executing command. */
+int command_index;
+
+/* A stack of file information records. If a new file is read in with
+ "@input", we remember the old input file state on this stack. */
+typedef struct fstack
+{
+ struct fstack *next;
+ char *filename;
+ char *text;
+ int size;
+ int offset;
+ int line_number;
+#ifdef TRACK_SRCFILE
+ char *src_filename;
+ int src_lineno;
+#endif /* TRACK_SRCFILE */
+} FSTACK;
+
+FSTACK *filestack = (FSTACK *) NULL;
+
+/* Stuff for nodes. */
+/* The current nodes node name. */
+char *current_node = (char *)NULL;
+
+/* The current nodes section level. */
+int current_section = 0;
+
+/* The filename of the current input file. This is never freed. */
+char *node_filename = (char *)NULL;
+#ifdef TRACK_SRCFILE
+char *node_src_filename = (char *)NULL;
+#endif /* TRACK_SRCFILE */
+
+/* What we remember for each node. */
+typedef struct tentry
+{
+ struct tentry *next_ent;
+ char *node; /* name of this node. */
+ char *prev; /* name of "Prev:" for this node. */
+ char *next; /* name of "Next:" for this node. */
+ char *up; /* name of "Up:" for this node. */
+ int position; /* output file position of this node. */
+ int line_no; /* defining line in source file. */
+ char *filename; /* The file that this node was found in. */
+#ifdef TRACK_SRCFILE
+ char *src_filename; /* The ORIG file that this node was found in. */
+ int src_lineno; /* defining line in ORIG source file. */
+#endif /* TRACK_SRCFILE */
+ int touched; /* non-zero means this node has been referenced. */
+ int flags; /* Room for growth. Right now, contains 1 bit. */
+} TAG_ENTRY;
+
+/* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
+ we turn on this flag bit in node-b's tag entry. This means that when
+ it is time to validate node-b, we don't report an additional error
+ if there was no "Prev" field. */
+#define PREV_ERROR 0x1
+#define NEXT_ERROR 0x2
+#define UP_ERROR 0x4
+#define NO_WARN 0x8
+#define IS_TOP 0x10
+
+TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
+
+#define HAVE_MACROS
+#if defined (HAVE_MACROS)
+/* Macro definitions for user-defined commands. */
+typedef struct {
+ char *name; /* Name of the macro. */
+ char *definition; /* Definition text. */
+ char *filename; /* File where this macro is defined. */
+ int lineno; /* Line number within FILENAME. */
+} MACRO_DEF;
+
+void add_macro (), execute_macro ();
+MACRO_DEF *find_macro (), *delete_macro ();
+#endif /* HAVE_MACROS */
+
+/* Menu reference, *note reference, and validation hacking. */
+
+/* The various references that we know about. */
+enum reftype
+{
+ menu_reference, followed_reference
+};
+
+/* A structure to remember references with. A reference to a node is
+ either an entry in a menu, or a cross-reference made with [px]ref. */
+typedef struct node_ref
+{
+ struct node_ref *next;
+ char *node; /* Name of node referred to. */
+ char *containing_node; /* Name of node containing this reference. */
+ int line_no; /* Line number where the reference occurs. */
+#ifdef TRACK_SRCFILE
+ int src_lineno;
+#endif /* TRACK_SRCFILE */
+ int section; /* Section level where the reference occurs. */
+ char *filename; /* Name of file where the reference occurs. */
+#ifdef TRACK_SRCFILE
+ char *src_filename;
+#endif /* TRACK_SRCFILE */
+ enum reftype type; /* Type of reference, either menu or note. */
+} NODE_REF;
+
+/* The linked list of such structures. */
+NODE_REF *node_references = (NODE_REF *) NULL;
+
+/* Flag which tells us whether to examine menu lines or not. */
+int in_menu = 0;
+
+/* Flags controlling the operation of the program. */
+
+/* Default is to notify users of bad choices. */
+int print_warnings = 1;
+
+/* Default is to check node references. */
+int validating = 1;
+
+/* Non-zero means do not output "Node: Foo" for node separations. */
+int no_headers = 0;
+
+/* Number of errors that we tolerate on a given fileset. */
+int max_error_level = 100;
+
+/* Maximum number of references to a single node before complaining. */
+int reference_warning_limit = 1000;
+
+/* Non-zero means print out information about what is going on when it
+ is going on. */
+int verbose_mode = 0;
+
+/* The list of commands that we hack in texinfo. Each one
+ has an associated function. When the command is encountered in the
+ text, the associated function is called with START as the argument.
+ If the function expects arguments in braces, it remembers itself on
+ the stack. When the corresponding close brace is encountered, the
+ function is called with END as the argument. */
+
+#define START 0
+#define END 1
+
+typedef struct brace_element
+{
+ struct brace_element *next;
+ FUNCTION *proc;
+ int pos, line;
+#ifdef TRACK_SRCFILE
+ int src_lineno;
+#endif /* TRACK_SRCFILE */
+} BRACE_ELEMENT;
+
+BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
+
+/* Forward declarations. */
+
+int insert_self (), cm_ignore_line ();
+
+int
+ cm_tex (), cm_asterisk (), cm_dots (), cm_bullet (), cm_TeX (),
+ cm_copyright (), cm_code (), cm_samp (), cm_file (), cm_kbd (),
+ cm_key (), cm_ctrl (), cm_var (), cm_dfn (), cm_emph (), cm_strong (),
+ cm_cite (), cm_italic (), cm_bold (), cm_roman (), cm_title (), cm_w (),
+ cm_refill (), cm_titlefont ();
+
+int
+ cm_chapter (), cm_unnumbered (), cm_appendix (), cm_top (),
+ cm_section (), cm_unnumberedsec (), cm_appendixsec (),
+ cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
+ cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec (),
+ cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (),
+ cm_majorheading ();
+
+/* All @defxxx commands map to cm_defun (). */
+int cm_defun ();
+
+int
+ cm_node (), cm_menu (), cm_xref (), cm_ftable (), cm_vtable (), cm_pxref (),
+ cm_inforef (), cm_quotation (), cm_display (), cm_itemize (),
+ cm_enumerate (), cm_table (), cm_itemx (), cm_noindent (), cm_setfilename (),
+ cm_br (), cm_sp (), cm_page (), cm_group (), cm_center (), cm_include (),
+ cm_bye (), cm_item (), cm_end (), cm_infoinclude (), cm_ifinfo (),
+ cm_kindex (), cm_cindex (), cm_findex (), cm_pindex (), cm_vindex (),
+ cm_tindex (), cm_asis (), cm_synindex (), cm_printindex (), cm_minus (),
+ cm_footnote (), cm_force_abbreviated_whitespace (), cm_example (),
+ cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (), cm_defindex (),
+ cm_defcodeindex (), cm_sc (), cm_result (), cm_expansion (), cm_equiv (),
+ cm_print (), cm_error (), cm_point (), cm_today (), cm_flushleft (),
+ cm_flushright (), cm_smalllisp (), cm_finalout (), cm_math (),
+ cm_cartouche (), cm_ignore_sentence_ender ();
+
+#ifdef TRACK_SRCFILE
+int cm_srcfilename (), cm_srclineno ();
+#endif /* TRACK_SRCFILE */
+
+/* Conditionals. */
+int cm_set (), cm_clear (), cm_ifset (), cm_ifclear (), cm_value ();
+
+#if defined (HAVE_MACROS)
+/* Define a user-defined command which is simple substitution. */
+int cm_macro (), cm_unmacro ();
+#endif /* HAVE_MACROS */
+
+/* Options. */
+int cm_paragraphindent (), cm_footnotestyle ();
+
+/* Internals. */
+int do_nothing (), command_name_condition ();
+int misplaced_brace (), cm_obsolete ();
+
+typedef struct
+{
+ char *name;
+ FUNCTION *proc;
+ int argument_in_braces;
+} COMMAND;
+
+/* Stuff for defining commands on the fly. */
+COMMAND **user_command_array = (COMMAND **) NULL;
+int user_command_array_len = 0;
+
+#define NO_BRACE_ARGS 0
+#define BRACE_ARGS 1
+
+static COMMAND CommandTable[] = {
+ { "!", cm_ignore_sentence_ender, NO_BRACE_ARGS },
+ { "'", insert_self, NO_BRACE_ARGS },
+ { "*", cm_asterisk, NO_BRACE_ARGS },
+ { ".", cm_ignore_sentence_ender, NO_BRACE_ARGS },
+ { ":", cm_force_abbreviated_whitespace, NO_BRACE_ARGS },
+ { "?", cm_ignore_sentence_ender, NO_BRACE_ARGS },
+ { "@", insert_self, NO_BRACE_ARGS },
+ { " ", insert_self, NO_BRACE_ARGS },
+ { "\n", insert_self, NO_BRACE_ARGS },
+ { "TeX", cm_TeX, BRACE_ARGS },
+ { "`", insert_self, NO_BRACE_ARGS },
+ { "appendix", cm_appendix, NO_BRACE_ARGS },
+ { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
+ { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
+ { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
+ { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
+ { "asis", cm_asis, BRACE_ARGS },
+ { "b", cm_bold, BRACE_ARGS },
+ { "br", cm_br, NO_BRACE_ARGS },
+ { "bullet", cm_bullet, BRACE_ARGS },
+ { "bye", cm_bye, NO_BRACE_ARGS },
+ { "c", cm_ignore_line, NO_BRACE_ARGS },
+ { "cartouche", cm_cartouche, NO_BRACE_ARGS },
+ { "center", cm_center, NO_BRACE_ARGS },
+ { "chapheading", cm_chapheading, NO_BRACE_ARGS },
+ { "chapter", cm_chapter, NO_BRACE_ARGS },
+ { "cindex", cm_cindex, NO_BRACE_ARGS },
+ { "cite", cm_cite, BRACE_ARGS },
+ { "clear", cm_clear, NO_BRACE_ARGS },
+ { "code", cm_code, BRACE_ARGS },
+ { "comment", cm_ignore_line, NO_BRACE_ARGS },
+ { "contents", do_nothing, NO_BRACE_ARGS },
+ { "copyright", cm_copyright, BRACE_ARGS },
+ { "ctrl", cm_ctrl, BRACE_ARGS },
+ { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
+ { "defindex", cm_defindex, NO_BRACE_ARGS },
+ { "dfn", cm_dfn, BRACE_ARGS },
+
+/* The `def' commands. */
+ { "deffn", cm_defun, NO_BRACE_ARGS },
+ { "deffnx", cm_defun, NO_BRACE_ARGS },
+ { "defun", cm_defun, NO_BRACE_ARGS },
+ { "defunx", cm_defun, NO_BRACE_ARGS },
+ { "defmac", cm_defun, NO_BRACE_ARGS },
+ { "defmacx", cm_defun, NO_BRACE_ARGS },
+ { "defspec", cm_defun, NO_BRACE_ARGS },
+ { "defspecx", cm_defun, NO_BRACE_ARGS },
+ { "defvr", cm_defun, NO_BRACE_ARGS },
+ { "defvrx", cm_defun, NO_BRACE_ARGS },
+ { "defvar", cm_defun, NO_BRACE_ARGS },
+ { "defvarx", cm_defun, NO_BRACE_ARGS },
+ { "defopt", cm_defun, NO_BRACE_ARGS },
+ { "defoptx", cm_defun, NO_BRACE_ARGS },
+ { "deftypefn", cm_defun, NO_BRACE_ARGS },
+ { "deftypefnx", cm_defun, NO_BRACE_ARGS },
+ { "deftypefun", cm_defun, NO_BRACE_ARGS },
+ { "deftypefunx", cm_defun, NO_BRACE_ARGS },
+ { "deftypevr", cm_defun, NO_BRACE_ARGS },
+ { "deftypevrx", cm_defun, NO_BRACE_ARGS },
+ { "deftypevar", cm_defun, NO_BRACE_ARGS },
+ { "deftypevarx", cm_defun, NO_BRACE_ARGS },
+ { "defcv", cm_defun, NO_BRACE_ARGS },
+ { "defcvx", cm_defun, NO_BRACE_ARGS },
+ { "defivar", cm_defun, NO_BRACE_ARGS },
+ { "defivarx", cm_defun, NO_BRACE_ARGS },
+ { "defop", cm_defun, NO_BRACE_ARGS },
+ { "defopx", cm_defun, NO_BRACE_ARGS },
+ { "defmethod", cm_defun, NO_BRACE_ARGS },
+ { "defmethodx", cm_defun, NO_BRACE_ARGS },
+ { "deftypemethod", cm_defun, NO_BRACE_ARGS },
+ { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
+ { "deftp", cm_defun, NO_BRACE_ARGS },
+ { "deftpx", cm_defun, NO_BRACE_ARGS },
+/* The end of the `def' commands. */
+
+ { "display", cm_display, NO_BRACE_ARGS },
+ { "dots", cm_dots, BRACE_ARGS },
+ { "dmn", do_nothing, BRACE_ARGS },
+ { "emph", cm_emph, BRACE_ARGS },
+ { "end", cm_end, NO_BRACE_ARGS },
+ { "enumerate", cm_enumerate, NO_BRACE_ARGS },
+ { "equiv", cm_equiv, BRACE_ARGS },
+ { "error", cm_error, BRACE_ARGS },
+ { "example", cm_example, NO_BRACE_ARGS },
+ { "exdent", cm_exdent, NO_BRACE_ARGS },
+ { "expansion", cm_expansion, BRACE_ARGS },
+ { "file", cm_file, BRACE_ARGS },
+ { "findex", cm_findex, NO_BRACE_ARGS },
+ { "finalout", do_nothing, NO_BRACE_ARGS },
+ { "flushleft", cm_flushleft, NO_BRACE_ARGS },
+ { "flushright", cm_flushright, NO_BRACE_ARGS },
+ { "format", cm_format, NO_BRACE_ARGS },
+ { "ftable", cm_ftable, NO_BRACE_ARGS },
+ { "group", cm_group, NO_BRACE_ARGS },
+ { "heading", cm_heading, NO_BRACE_ARGS },
+ { "headings", cm_ignore_line, NO_BRACE_ARGS },
+ { "i", cm_italic, BRACE_ARGS },
+ { "iappendix", cm_appendix, NO_BRACE_ARGS },
+ { "iappendixsection", cm_appendixsec, NO_BRACE_ARGS },
+ { "iappendixsec", cm_appendixsec, NO_BRACE_ARGS },
+ { "iappendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
+ { "iappendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
+ { "ichapter", cm_chapter, NO_BRACE_ARGS },
+ { "ifclear", cm_ifclear, NO_BRACE_ARGS },
+ { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
+ { "ifset", cm_ifset, NO_BRACE_ARGS },
+ { "iftex", command_name_condition, NO_BRACE_ARGS },
+ { "ignore", command_name_condition, NO_BRACE_ARGS },
+ { "include", cm_include, NO_BRACE_ARGS },
+ { "inforef", cm_inforef, BRACE_ARGS },
+ { "input", cm_include, NO_BRACE_ARGS },
+ { "isection", cm_section, NO_BRACE_ARGS },
+ { "isubsection", cm_subsection, NO_BRACE_ARGS },
+ { "isubsubsection", cm_subsubsection, NO_BRACE_ARGS },
+ { "item", cm_item, NO_BRACE_ARGS },
+ { "itemize", cm_itemize, NO_BRACE_ARGS },
+ { "itemx", cm_itemx, NO_BRACE_ARGS },
+ { "iunnumbered", cm_unnumbered, NO_BRACE_ARGS },
+ { "iunnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
+ { "iunnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
+ { "iunnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
+ { "kbd", cm_kbd, BRACE_ARGS },
+ { "key", cm_key, BRACE_ARGS },
+ { "kindex", cm_kindex, NO_BRACE_ARGS },
+ { "lisp", cm_lisp, NO_BRACE_ARGS },
+ { "macro", cm_macro, NO_BRACE_ARGS },
+ { "majorheading", cm_majorheading, NO_BRACE_ARGS },
+ { "math", cm_math, BRACE_ARGS },
+ { "menu", cm_menu, NO_BRACE_ARGS },
+ { "minus", cm_minus, BRACE_ARGS },
+ { "need", cm_ignore_line, NO_BRACE_ARGS },
+ { "node", cm_node, NO_BRACE_ARGS },
+ { "noindent", cm_noindent, NO_BRACE_ARGS },
+ { "nwnode", cm_node, NO_BRACE_ARGS },
+ { "overfullrule", cm_ignore_line, NO_BRACE_ARGS },
+ { "page", do_nothing, NO_BRACE_ARGS },
+ { "pindex", cm_pindex, NO_BRACE_ARGS },
+ { "point", cm_point, BRACE_ARGS },
+ { "print", cm_print, BRACE_ARGS },
+ { "printindex", cm_printindex, NO_BRACE_ARGS },
+ { "pxref", cm_pxref, BRACE_ARGS },
+ { "quotation", cm_quotation, NO_BRACE_ARGS },
+ { "r", cm_roman, BRACE_ARGS },
+ { "ref", cm_xref, BRACE_ARGS },
+ { "refill", cm_refill, NO_BRACE_ARGS },
+ { "result", cm_result, BRACE_ARGS },
+ { "samp", cm_samp, BRACE_ARGS },
+ { "sc", cm_sc, BRACE_ARGS },
+ { "section", cm_section, NO_BRACE_ARGS },
+ { "set", cm_set, NO_BRACE_ARGS },
+ { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
+ { "setchapterstyle", cm_ignore_line, NO_BRACE_ARGS },
+ { "setfilename", cm_setfilename, NO_BRACE_ARGS },
+ { "settitle", cm_ignore_line, NO_BRACE_ARGS },
+ { "shortcontents", do_nothing, NO_BRACE_ARGS },
+ { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
+ { "smallexample", cm_smallexample, NO_BRACE_ARGS },
+ { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
+ { "sp", cm_sp, NO_BRACE_ARGS },
+#ifdef TRACK_SRCFILE
+ { "srcfilename", cm_srcfilename, NO_BRACE_ARGS },
+ { "srclineno", cm_srclineno, NO_BRACE_ARGS },
+#endif /* TRACK_SRCFILE */
+ { "strong", cm_strong, BRACE_ARGS },
+ { "subheading", cm_subheading, NO_BRACE_ARGS },
+ { "subsection", cm_subsection, NO_BRACE_ARGS },
+ { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
+ { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
+ { "summarycontents", do_nothing, NO_BRACE_ARGS },
+ { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
+ { "synindex", cm_synindex, NO_BRACE_ARGS },
+ { "t", cm_title, BRACE_ARGS },
+ { "table", cm_table, NO_BRACE_ARGS },
+ { "tex", command_name_condition, NO_BRACE_ARGS },
+ { "tindex", cm_tindex, NO_BRACE_ARGS },
+ { "titlefont", cm_titlefont, BRACE_ARGS },
+ { "titlepage", command_name_condition, NO_BRACE_ARGS },
+ { "titlespec", command_name_condition, NO_BRACE_ARGS },
+ { "today", cm_today, BRACE_ARGS },
+ { "top", cm_top, NO_BRACE_ARGS },
+ { "unmacro", cm_unmacro, NO_BRACE_ARGS },
+ { "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
+ { "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
+ { "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
+ { "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
+ { "value", cm_value, BRACE_ARGS },
+ { "var", cm_var, BRACE_ARGS },
+ { "vindex", cm_vindex, NO_BRACE_ARGS },
+ { "vtable", cm_vtable, NO_BRACE_ARGS },
+ { "w", cm_w, BRACE_ARGS },
+ { "xref", cm_xref, BRACE_ARGS },
+ { "{", insert_self, NO_BRACE_ARGS },
+ { "}", insert_self, NO_BRACE_ARGS },
+
+ /* Some obsoleted commands. */
+ { "infotop", cm_obsolete, NO_BRACE_ARGS },
+ { "infounnumbered", cm_obsolete, NO_BRACE_ARGS },
+ { "infounnumberedsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infounnumberedsubsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infounnumberedsubsubsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infoappendix", cm_obsolete, NO_BRACE_ARGS },
+ { "infoappendixsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infoappendixsubsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infoappendixsubsubsec", cm_obsolete, NO_BRACE_ARGS },
+ { "infochapter", cm_obsolete, NO_BRACE_ARGS },
+ { "infosection", cm_obsolete, NO_BRACE_ARGS },
+ { "infosubsection", cm_obsolete, NO_BRACE_ARGS },
+ { "infosubsubsection", cm_obsolete, NO_BRACE_ARGS },
+
+ /* Now @include does what this was supposed to. */
+ { "infoinclude", cm_infoinclude, NO_BRACE_ARGS },
+ { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
+ { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
+ { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
+
+ {(char *) NULL, (FUNCTION *) NULL}, NO_BRACE_ARGS};
+
+int major_version = 1;
+int minor_version = 47;
+
+struct option long_options[] =
+{
+ { "error-limit", 1, 0, 'e' }, /* formerly -el */
+ { "fill-column", 1, 0, 'f' }, /* formerly -fc */
+ { "footnote-style", 1, 0, 's' }, /* formerly -ft */
+ { "no-headers", 0, &no_headers, 1 }, /* Do not output Node: foo */
+ { "no-pointer-validate", 0, &validating, 0 }, /* formerly -nv */
+ { "no-validate", 0, &validating, 0 }, /* formerly -nv */
+ { "no-split", 0, &splitting, 0 }, /* formerly -ns */
+ { "no-warn", 0, &print_warnings, 0 }, /* formerly -nw */
+ { "number-footnotes", 0, &number_footnotes, 1 },
+ { "no-number-footnotes", 0, &number_footnotes, 0 },
+ { "output", 1, 0, 'o' },
+ { "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */
+ { "reference-limit", 1, 0, 'r' }, /* formerly -rl */
+ { "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */
+ { "version", 0, 0, 'V' },
+ {NULL, 0, NULL, 0}
+};
+
+/* Values for calling handle_variable_internal (). */
+#define SET 1
+#define CLEAR 2
+#define IFSET 3
+#define IFCLEAR 4
+
+/* **************************************************************** */
+/* */
+/* Main () Start of code */
+/* */
+/* **************************************************************** */
+
+/* For each file mentioned in the command line, process it, turning
+ texinfo commands into wonderfully formatted output text. */
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int errors_printed;
+ char *filename_part ();
+ int c, ind;
+
+ /* The name of this program is the last filename in argv[0]. */
+ progname = filename_part (argv[0]);
+
+ /* Parse argument flags from the input line. */
+ while ((c = getopt_long
+ (argc, argv, "D:U:I:f:o:p:e:r:s:V", long_options, &ind))
+ != EOF)
+ {
+ if (c == 0 && long_options[ind].flag == 0)
+ c = long_options[ind].val;
+
+ switch (c)
+ {
+ /* User specified variable to set or clear? */
+ case 'D':
+ case 'U':
+ handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
+ break;
+
+ /* User specified include file path? */
+ case 'I':
+ if (!include_files_path)
+ include_files_path = savestring (".");
+
+ include_files_path = (char *)
+ xrealloc (include_files_path,
+ 2 + strlen (include_files_path) + strlen (optarg));
+ strcat (include_files_path, ":");
+ strcat (include_files_path, optarg);
+ break;
+
+ /* User specified fill_column? */
+ case 'f':
+ if (sscanf (optarg, "%d", &fill_column) != 1)
+ usage ();
+ break;
+
+ /* User specified output file? */
+ case 'o':
+ command_output_filename = savestring (optarg);
+ break;
+
+ /* User specified paragraph indent (paragraph_start_index)? */
+ case 'p':
+ if (set_paragraph_indent (optarg) < 0)
+ usage ();
+ break;
+
+ /* User specified error level? */
+ case 'e':
+ if (sscanf (optarg, "%d", &max_error_level) != 1)
+ usage ();
+ break;
+
+ /* User specified reference warning limit? */
+ case 'r':
+ if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
+ usage ();
+ break;
+
+ /* User specified footnote style? */
+ case 's':
+ if (set_footnote_style (optarg) < 0)
+ usage ();
+ footnote_style_preset = 1;
+ break;
+
+ /* User requested version info? */
+ case 'V':
+ print_version_info ();
+ exit (NO_ERROR);
+ break;
+
+ case '?':
+ usage ();
+ }
+ }
+
+ if (optind == argc)
+ usage ();
+ else if (verbose_mode)
+ print_version_info ();
+
+ /* Remaining arguments are file names of texinfo files.
+ Convert them, one by one. */
+ while (optind != argc)
+ convert (argv[optind++]);
+
+ if (errors_printed)
+ exit (SYNTAX);
+ else
+ exit (NO_ERROR);
+}
+
+/* Display the version info of this invocation of Makeinfo. */
+print_version_info ()
+{
+ fprintf (stderr, "This is GNU Makeinfo version %d.%d.\n",
+ major_version, minor_version);
+}
+
+/* **************************************************************** */
+/* */
+/* Generic Utilities */
+/* */
+/* **************************************************************** */
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+ int nbytes;
+{
+ void *temp = (void *) malloc (nbytes);
+
+ if (nbytes && temp == (void *)NULL)
+ memory_error ("xmalloc", nbytes);
+
+ return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+ void *pointer;
+ int nbytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = (void *)xmalloc (nbytes);
+ else
+ temp = (void *)realloc (pointer, nbytes);
+
+ if (nbytes && !temp)
+ memory_error ("xrealloc", nbytes);
+
+ return (temp);
+}
+
+memory_error (callers_name, bytes_wanted)
+ char *callers_name;
+ int bytes_wanted;
+{
+ char printable_string[80];
+
+ sprintf (printable_string,
+ "Virtual memory exhausted in %s ()! Needed %d bytes.",
+ callers_name, bytes_wanted);
+
+ error (printable_string);
+ abort ();
+}
+
+/* Tell the user how to use this program. */
+usage ()
+{
+ fprintf (stderr, "Usage: %s [options] texinfo-file...\n\
+\n\
+This program accepts as input files of texinfo commands and text\n\
+and outputs a file suitable for reading with GNU Info.\n\
+\n\
+The options are:\n\
+`-I DIR' to add DIR to the directory search list for including\n\
+ files with the `@include' command.\n\
+-D VAR to define a variable, as with `@set'.\n\
+-U VAR to undefine a variable, as with `@clear'.\n\
+`--no-validate' to suppress node cross reference validation.\n\
+`--no-warn' to suppress warning messages (errors are still output).\n\
+`--no-split' to suppress the splitting of large files.\n\
+`--no-headers' to suppress the output of Node: Foo headers.\n\
+`--verbose' to print information about what is being done.\n\
+`--version' to print the version number of Makeinfo.\n\
+`--output FILE' or `-o FILE'\n\
+ to specify the output file. When you specify the\n\
+ output file in this way, any `@setfilename' in the\n\
+ input file is ignored.\n\
+`--paragraph-indent NUM'\n\
+ to set the paragraph indent to NUM (default %d).\n\
+`--fill-column NUM' to set the filling column to NUM (default %d).\n\
+`--error-limit NUM' to set the error limit to NUM (default %d).\n\
+`--reference-limit NUM'\n\
+ to set the reference warning limit to NUM (default %d).\n\
+`--footnote-style STYLE'\n\
+ to set the footnote style to STYLE. STYLE should\n\
+ either be `separate' to place footnotes in their own\n\
+ node, or `end', to place the footnotes at the end of\n\
+ the node in which they are defined (the default).\n\n",
+ progname, paragraph_start_indent,
+ fill_column, max_error_level, reference_warning_limit);
+ exit (FATAL);
+}
+
+/* **************************************************************** */
+/* */
+/* Manipulating Lists */
+/* */
+/* **************************************************************** */
+
+typedef struct generic_list {
+ struct generic_list *next;
+} GENERIC_LIST;
+
+/* Reverse the chain of structures in LIST. Output the new head
+ of the chain. You should always assign the output value of this
+ function to something, or you will lose the chain. */
+GENERIC_LIST *
+reverse_list (list)
+ register GENERIC_LIST *list;
+{
+ register GENERIC_LIST *next;
+ register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
+
+ while (list)
+ {
+ next = list->next;
+ list->next = prev;
+ prev = list;
+ list = next;
+ }
+ return (prev);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Pushing and Popping Files */
+/* */
+/* **************************************************************** */
+
+/* Find and load the file named FILENAME. Return a pointer to
+ the loaded file, or NULL if it can't be loaded. */
+char *
+find_and_load (filename)
+ char *filename;
+{
+ struct stat fileinfo;
+ int file, n, i, count = 0;
+ char *fullpath, *result, *get_file_info_in_path ();
+
+ result = fullpath = (char *)NULL;
+
+ fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
+
+ if (!fullpath)
+ goto error_exit;
+
+ filename = fullpath;
+
+ file = open (filename, O_RDONLY);
+ if (file < 0)
+ goto error_exit;
+
+ /* Load the file. */
+ result = (char *)xmalloc (fileinfo.st_size);
+
+ /* VMS stat lies about the st_size value. The actual number of
+ readable bytes is always less than this value. The arcane
+ mysteries of VMS/RMS are too much to probe, so this hack
+ suffices to make things work. */
+#if defined (VMS)
+ while ((n = read (file, result + count, fileinfo.st_size)) > 0)
+ count += n;
+ if (n == -1)
+#else /* !VMS */
+ count = fileinfo.st_size;
+ if (read (file, result, fileinfo.st_size) != fileinfo.st_size)
+#endif /* !VMS */
+ error_exit:
+ {
+ if (result)
+ free (result);
+
+ if (fullpath)
+ free (fullpath);
+
+ if (file != -1)
+ close (file);
+
+ return ((char *) NULL);
+ }
+ close (file);
+
+ /* Set the globals to the new file. */
+ input_text = result;
+ size_of_input_text = fileinfo.st_size;
+ input_filename = savestring (filename);
+ node_filename = savestring (filename);
+#ifdef TRACK_SRCFILE
+ node_src_filename = savestring (filename);
+#endif /* TRACK_SRCFILE */
+ input_text_offset = 0;
+ line_number = 1;
+#ifdef TRACK_SRCFILE
+ src_filename = savestring (filename);
+ src_lineno = 1;
+#endif /* TRACK_SRCFILE */
+ return (result);
+}
+
+/* Save the state of the current input file. */
+pushfile ()
+{
+ FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
+ newstack->filename = input_filename;
+ newstack->text = input_text;
+ newstack->size = size_of_input_text;
+ newstack->offset = input_text_offset;
+ newstack->line_number = line_number;
+#ifdef TRACK_SRCFILE
+ newstack->src_filename = src_filename;
+ newstack->src_lineno = src_lineno;
+#endif /* TRACK_SRCFILE */
+ newstack->next = filestack;
+
+ filestack = newstack;
+ push_node_filename ();
+}
+
+/* Make the current file globals be what is on top of the file stack. */
+popfile ()
+{
+ extern int executing_string;
+ FSTACK *temp = filestack;
+
+ if (!filestack)
+ abort (); /* My fault. I wonder what I did? */
+
+ /* Make sure that commands with braces have been satisfied. */
+ if (!executing_string)
+ discard_braces ();
+
+ /* Get the top of the stack into the globals. */
+ input_filename = filestack->filename;
+ input_text = filestack->text;
+ size_of_input_text = filestack->size;
+ input_text_offset = filestack->offset;
+ line_number = filestack->line_number;
+#ifdef TRACK_SRCFILE
+ src_filename = filestack->src_filename;
+ src_lineno = filestack->src_lineno;
+#endif /* TRACK_SRCFILE */
+
+ /* Pop the stack. */
+ filestack = filestack->next;
+ free (temp);
+ pop_node_filename ();
+}
+
+/* Flush all open files on the file stack. */
+flush_file_stack ()
+{
+ while (filestack)
+ {
+ free (input_filename);
+#ifdef TRACK_SRCFILE
+ free (src_filename);
+#endif /* TRACK_SRCFILE */
+ free (input_text);
+ popfile ();
+ }
+}
+
+int node_filename_stack_index = 0;
+int node_filename_stack_size = 0;
+char **node_filename_stack = (char **)NULL;
+#ifdef TRACK_SRCFILE
+char **node_src_filename_stack = (char **)NULL;
+#endif /* TRACK_SRCFILE */
+
+push_node_filename ()
+{
+ if (node_filename_stack_index + 1 > node_filename_stack_size)
+ {
+ if (!node_filename_stack)
+ {
+ node_filename_stack =
+ (char **)xmalloc ((node_filename_stack_size += 10)
+ * sizeof (char *));
+#ifdef TRACK_SRCFILE
+ node_src_filename_stack =
+ (char **)xmalloc ((node_filename_stack_size += 10)
+ * sizeof (char *));
+#endif /* TRACK_SRCFILE */
+ }
+ else
+ {
+ node_filename_stack =
+ (char **)xrealloc (node_filename_stack,
+ (node_filename_stack_size + 10)
+ * sizeof (char *));
+#ifdef TRACK_SRCFILE
+ node_src_filename_stack =
+ (char **)xrealloc (node_filename_stack,
+ (node_filename_stack_size + 10)
+ * sizeof (char *));
+#endif /* TRACK_SRCFILE */
+ }
+ }
+
+ node_filename_stack[node_filename_stack_index] = node_filename;
+#ifdef TRACK_SRCFILE
+ node_src_filename_stack[node_filename_stack_index] = node_src_filename;
+#endif /* TRACK_SRCFILE */
+ node_filename_stack_index++;
+}
+
+pop_node_filename ()
+{
+ node_filename = node_filename_stack[--node_filename_stack_index];
+#ifdef TRACK_SRCFILE
+ node_src_filename = node_src_filename_stack[node_filename_stack_index];
+#endif /* TRACK_SRCFILE */
+
+}
+
+/* Return just the simple part of the filename; i.e. the
+ filename without the path information, or extensions.
+ This conses up a new string. */
+char *
+filename_part (filename)
+ char *filename;
+{
+ register int i = strlen (filename) - 1;
+
+ while (i && filename[i] != '/')
+ i--;
+ if (filename[i] == '/')
+ i++;
+
+#if defined (REMOVE_OUTPUT_EXTENSIONS)
+ result = savestring (&filename[i]);
+
+ /* See if there is an extension to remove. If so, remove it. */
+ if (rindex (result, '.'))
+ *(rindex (result, '.')) = '\0';
+ return (result);
+#else
+ return (savestring (&filename[i]));
+#endif /* REMOVE_OUTPUT_EXTENSIONS */
+}
+
+/* Return the pathname part of filename. This can be NULL. */
+char *
+pathname_part (filename)
+ char *filename;
+{
+ char *expand_filename ();
+ char *result = (char *) NULL;
+ register int i;
+
+ filename = expand_filename (filename, "");
+
+ i = strlen (filename) - 1;
+
+ while (i && filename[i] != '/')
+ i--;
+ if (filename[i] == '/')
+ i++;
+
+ if (i)
+ {
+ result = (char *)xmalloc (1 + i);
+ strncpy (result, filename, i);
+ result[i] = '\0';
+ }
+ free (filename);
+ return (result);
+}
+
+/* Return the expansion of FILENAME. */
+char *
+expand_filename (filename, input_name)
+ char *filename, *input_name;
+{
+ char *full_pathname ();
+ filename = full_pathname (filename);
+
+ if (filename[0] == '.')
+ return (filename);
+
+ if (filename[0] != '/' && input_name[0] == '/')
+ {
+ /* Make it so that relative names work. */
+ char *result;
+ int i = strlen (input_name) - 1;
+
+ result = (char *)xmalloc (1 + strlen (input_name) + strlen (filename));
+ strcpy (result, input_name);
+
+ while (result[i] != '/' && i)
+ i--;
+
+ if (result[i] == '/')
+ i++;
+
+ strcpy (&result[i], filename);
+ free (filename);
+ return (result);
+ }
+ return (filename);
+}
+
+/* Return the full path to FILENAME. */
+char *
+full_pathname (filename)
+ char *filename;
+{
+ int initial_character;
+
+ if (filename && (initial_character = *filename))
+ {
+ if (initial_character == '/')
+ return (savestring (filename));
+ if (initial_character != '~')
+ {
+ return (savestring (filename));
+ }
+ else
+ {
+ if (filename[1] == '/')
+ {
+ /* Return the concatenation of HOME and the rest of the string. */
+ char *temp_home;
+ char *temp_name;
+
+ temp_home = (char *) getenv ("HOME");
+ temp_name = (char *)xmalloc (strlen (&filename[2])
+ + 1
+ + temp_home ? strlen (temp_home)
+ : 0);
+ if (temp_home)
+ strcpy (temp_name, temp_home);
+
+ strcat (temp_name, &filename[2]);
+ return (temp_name);
+ }
+ else
+ {
+ struct passwd *user_entry;
+ int i, c;
+ char *username = (char *)xmalloc (257);
+ char *temp_name;
+
+ for (i = 1; c = filename[i]; i++)
+ {
+ if (c == '/')
+ break;
+ else
+ username[i - 1] = c;
+ }
+ if (c)
+ username[i - 1] = '\0';
+
+ user_entry = getpwnam (username);
+
+ if (!user_entry)
+ return (savestring (filename));
+
+ temp_name = (char *)xmalloc (1 + strlen (user_entry->pw_dir)
+ + strlen (&filename[i]));
+ strcpy (temp_name, user_entry->pw_dir);
+ strcat (temp_name, &filename[i]);
+ return (temp_name);
+ }
+ }
+ }
+ else
+ {
+ return (savestring (filename));
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Error Handling */
+/* */
+/* **************************************************************** */
+
+/* Number of errors encountered. */
+int errors_printed = 0;
+
+/* Print the last error gotten from the file system. */
+fs_error (filename)
+ char *filename;
+{
+ remember_error ();
+ perror (filename);
+ return (0);
+}
+
+/* Print an error message, and return false. */
+error (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ remember_error ();
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, "\n");
+ return ((int) 0);
+}
+
+/* Just like error (), but print the line number as well. */
+line_error (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ remember_error ();
+#ifdef TRACK_SRCFILE
+ fprintf (stderr, "%s:%d: ", src_filename, src_lineno);
+#else
+ fprintf (stderr, "%s:%d: ", input_filename, line_number);
+#endif /* TRACK_SRCFILE */
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, ".\n");
+ return ((int) 0);
+}
+
+warning (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ if (print_warnings)
+ {
+#ifdef TRACK_SRCFILE
+ fprintf (stderr, "%s:%d: Warning: ", src_filename, src_lineno);
+#else
+ fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
+#endif /* TRACK_SRCFILE */
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, ".\n");
+ }
+ return ((int) 0);
+}
+
+/* Remember that an error has been printed. If this is the first
+ error printed, then tell them which program is printing them.
+ If more than max_error_level have been printed, then exit the
+ program. */
+remember_error ()
+{
+ errors_printed++;
+ if (max_error_level && (errors_printed > max_error_level))
+ {
+ fprintf (stderr, "Too many errors! Gave up.\n");
+ flush_file_stack ();
+ cm_bye ();
+ exit (1);
+ }
+}
+
+
+/* **************************************************************** */
+/* */
+/* Hacking Tokens and Strings */
+/* */
+/* **************************************************************** */
+
+/* Return the next token as a string pointer. We cons the
+ string. */
+char *
+read_token ()
+{
+ int i, character;
+ char *result;
+
+ /* If the first character to be read is self-delimiting, then that
+ is the command itself. */
+ character = curchar ();
+ if (self_delimiting (character))
+ {
+ input_text_offset++;
+ result = savestring (" ");
+ *result = character;
+ return (result);
+ }
+
+ for (i = 0; ((input_text_offset != size_of_input_text)
+ && (character = curchar ())
+ && command_char (character));
+ i++, input_text_offset++);
+ result = (char *)xmalloc (i + 1);
+ bcopy (&input_text[input_text_offset - i], result, i);
+ result[i] = '\0';
+ return (result);
+}
+
+/* Return non-zero if CHARACTER is self-delimiting. */
+int
+self_delimiting (character)
+ int character;
+{
+ return (member (character, "{}:.@*'`,!?; \n"));
+}
+
+/* Clear whitespace from the front and end of string. */
+canon_white (string)
+ char *string;
+{
+ int len = strlen (string);
+ int x;
+
+ if (!len)
+ return;
+
+ for (x = 0; x < len; x++)
+ {
+ if (!whitespace (string[x]))
+ {
+ strcpy (string, string + x);
+ break;
+ }
+ }
+ len = strlen (string);
+ if (len)
+ len--;
+ while (len > -1 && cr_or_whitespace (string[len]))
+ len--;
+ string[len + 1] = '\0';
+}
+
+/* Bash STRING, replacing all whitespace with just one space. */
+fix_whitespace (string)
+ char *string;
+{
+ char *temp = (char *)xmalloc (strlen (string) + 1);
+ int string_index = 0;
+ int temp_index = 0;
+ int c;
+
+ canon_white (string);
+
+ while (string[string_index])
+ {
+ c = temp[temp_index++] = string[string_index++];
+
+ if (c == ' ' || c == '\n' || c == '\t')
+ {
+ temp[temp_index - 1] = ' ';
+ while ((c = string[string_index]) && (c == ' ' ||
+ c == '\t' ||
+ c == '\n'))
+ string_index++;
+ }
+ }
+ temp[temp_index] = '\0';
+ strcpy (string, temp);
+ free (temp);
+}
+
+/* Discard text until the desired string is found. The string is
+ included in the discarded text. */
+discard_until (string)
+ char *string;
+{
+ int temp = search_forward (string, input_text_offset);
+
+ int tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
+ int from = input_text_offset;
+
+ /* Find out what line we are on. */
+ while (from != tt)
+ if (input_text[from++] == '\n')
+#ifdef TRACK_SRCFILE
+ { line_number++; src_lineno++; }
+#else
+ line_number++;
+#endif /* TRACK_SRCFILE */
+
+ if (temp < 0)
+ {
+ input_text_offset = size_of_input_text - strlen (string);
+
+ if (strcmp (string, "\n") != 0)
+ {
+ line_error ("Expected `%s'", string);
+ return;
+ }
+ }
+ else
+ input_text_offset = temp;
+
+ input_text_offset += strlen (string);
+}
+
+/* Read characters from the file until we are at MATCH.
+ Place the characters read into STRING.
+ On exit input_text_offset is after the match string.
+ Return the offset where the string starts. */
+int
+get_until (match, string)
+ char *match, **string;
+{
+ int len, current_point, x, new_point, tem;
+
+ current_point = x = input_text_offset;
+ new_point = search_forward (match, input_text_offset);
+
+ if (new_point < 0)
+ new_point = size_of_input_text;
+ len = new_point - current_point;
+
+ /* Keep track of which line number we are at. */
+ tem = new_point + (strlen (match) - 1);
+ while (x != tem)
+ if (input_text[x++] == '\n')
+#ifdef TRACK_SRCFILE
+ { line_number++; src_lineno++; }
+#else
+ line_number++;
+#endif /* TRACK_SRCFILE */
+
+ *string = (char *)xmalloc (len + 1);
+
+ bcopy (&input_text[current_point], *string, len);
+ (*string)[len] = '\0';
+
+ /* Now leave input_text_offset in a consistent state. */
+ input_text_offset = tem;
+
+ if (input_text_offset > size_of_input_text)
+ input_text_offset = size_of_input_text;
+
+ return (new_point);
+}
+
+/* Read characters from the file until we are at MATCH or end of line.
+ Place the characters read into STRING. */
+get_until_in_line (match, string)
+ char *match, **string;
+{
+ int real_bottom, temp;
+
+ real_bottom = size_of_input_text;
+ temp = search_forward ("\n", input_text_offset);
+
+ if (temp < 0)
+ temp = size_of_input_text;
+
+ size_of_input_text = temp;
+ get_until (match, string);
+ size_of_input_text = real_bottom;
+}
+
+get_rest_of_line (string)
+ char **string;
+{
+ get_until ("\n", string);
+ canon_white (*string);
+
+ if (curchar () == '\n') /* as opposed to the end of the file... */
+ {
+ line_number++;
+#ifdef TRACK_SRCFILE
+ src_lineno++;
+#endif /* TRACK_SRCFILE */
+ input_text_offset++;
+ }
+}
+
+/* Backup the input pointer to the previous character, keeping track
+ of the current line number. */
+backup_input_pointer ()
+{
+ if (input_text_offset)
+ {
+ input_text_offset--;
+ if (curchar () == '\n')
+ line_number--;
+ }
+}
+
+/* Read characters from the file until we are at MATCH or closing brace.
+ Place the characters read into STRING. */
+get_until_in_braces (match, string)
+ char *match, **string;
+{
+ int i, brace = 0;
+ int match_len = strlen (match);
+ char *temp;
+
+ for (i = input_text_offset; i < size_of_input_text; i++)
+ {
+ if (input_text[i] == '{')
+ brace++;
+ else if (input_text[i] == '}')
+ brace--;
+ else if (input_text[i] == '\n')
+#ifdef TRACK_SRCFILE
+ { line_number++; src_lineno++; }
+#else
+ line_number++;
+#endif /* TRACK_SRCFILE */
+
+ if (brace < 0 ||
+ (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
+ break;
+ }
+
+ match_len = i - input_text_offset;
+ temp = (char *)xmalloc (2 + match_len);
+ strncpy (temp, input_text + input_text_offset, match_len);
+ temp[match_len] = '\0';
+ input_text_offset = i;
+ *string = temp;
+}
+
+/* **************************************************************** */
+/* */
+/* Converting the File */
+/* */
+/* **************************************************************** */
+
+/* Convert the file named by NAME. The output is saved on the file
+ named as the argument to the @setfilename command. */
+static char *suffixes[] = {
+ "",
+ ".texinfo",
+ ".texi",
+ ".txinfo",
+ (char *)NULL
+};
+
+convert (name)
+ char *name;
+{
+ char *real_output_filename, *expand_filename (), *filename_part ();
+ char *filename = (char *)xmalloc (strlen (name) + 50);
+ register int i;
+
+ init_tag_table ();
+ init_indices ();
+ init_internals ();
+ init_paragraph ();
+
+ /* Try to load the file specified by NAME. If the file isn't found, and
+ there is no suffix in NAME, then try NAME.texinfo, and NAME.texi. */
+ for (i = 0; suffixes[i]; i++)
+ {
+ strcpy (filename, name);
+ strcat (filename, suffixes[i]);
+
+ if (find_and_load (filename))
+ break;
+
+ if (!suffixes[i][0] && rindex (filename, '.'))
+ {
+ fs_error (filename);
+ free (filename);
+ return;
+ }
+ }
+
+ if (!suffixes[i])
+ {
+ fs_error (name);
+ free (filename);
+ return;
+ }
+
+#ifdef TRACK_SRCFILE
+ {
+ input_filename = filename;
+ src_filename = filename;
+ }
+#else
+ input_filename = filename;
+#endif /* TRACK_SRCFILE */
+
+ /* Search this file looking for the special string which starts conversion.
+ Once found, we may truly begin. */
+
+ input_text_offset = search_forward ("@setfilename", 0);
+
+ if (input_text_offset < 0)
+ {
+ if (!command_output_filename)
+ {
+ error ("No `@setfilename' found in `%s'", name);
+ goto finished;
+ }
+ }
+ else
+ input_text_offset += strlen ("@setfilename");
+
+ real_output_filename = (char *)NULL;
+
+ if (!command_output_filename)
+ get_until ("\n", &output_filename);
+ else
+ {
+ discard_until ("\n");
+ real_output_filename = output_filename = command_output_filename;
+ command_output_filename = (char *)NULL;
+ }
+
+ canon_white (output_filename);
+ printf ("Making info file `%s' from `%s'.\n", output_filename, name);
+
+ if (verbose_mode)
+ fprintf (stderr, " The input file contains %d characters.\n",
+ size_of_input_text);
+
+ if (real_output_filename &&
+ strcmp (real_output_filename, "-") == 0)
+ {
+ output_stream = stdout;
+ }
+ else
+ {
+ if (!real_output_filename)
+ real_output_filename = expand_filename (output_filename, name);
+
+ output_stream = fopen (real_output_filename, "w");
+ }
+
+ if (output_stream == NULL)
+ {
+ fs_error (real_output_filename);
+ goto finished;
+ }
+
+ /* Make the displayable filename from output_filename. Only the base
+ portion of the filename need be displayed. */
+ pretty_output_filename = filename_part (output_filename);
+
+ /* For this file only, count the number of newlines from the top of
+ the file to here. This way, we keep track of line numbers for
+ error reporting. Line_number starts at 1, since the user isn't
+ zero-based. */
+ {
+ int temp = 0;
+ line_number = 1;
+#ifdef TRACK_SRCFILE
+ src_lineno = 1;
+#endif /* TRACK_SRCFILE */
+ while (temp != input_text_offset)
+ if (input_text[temp++] == '\n')
+#ifdef TRACK_SRCFILE
+ { line_number++; src_lineno++; }
+#else
+ line_number++;
+#endif /* TRACK_SRCFILE */
+ }
+
+ add_word_args ("This is Info file %s, produced by Makeinfo-%d.%d from ",
+ output_filename, major_version, minor_version);
+ add_word_args ("the input file %s.\n", input_filename);
+ close_paragraph ();
+
+ reader_loop ();
+
+finished:
+ close_paragraph ();
+ flush_file_stack ();
+ if (output_stream != NULL)
+ {
+ output_pending_notes ();
+ free_pending_notes ();
+ if (tag_table != NULL)
+ {
+ tag_table = (TAG_ENTRY *) reverse_list (tag_table);
+ if (!no_headers)
+ write_tag_table ();
+ }
+
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+ /* If validating, then validate the entire file right now. */
+ if (validating)
+ validate_file (real_output_filename, tag_table);
+
+ /* This used to test && !errors_printed.
+ But some files might have legit warnings. So split anyway. */
+ if (splitting)
+ split_file (real_output_filename, 0);
+ }
+}
+
+free_and_clear (pointer)
+ char **pointer;
+{
+ if ((*pointer) != (char *) NULL)
+ {
+ free (*pointer);
+ *pointer = (char *) NULL;
+ }
+}
+
+ /* Initialize some state. */
+init_internals ()
+{
+ free_and_clear (&current_node);
+ free_and_clear (&output_filename);
+ free_and_clear (&command);
+ free_and_clear (&input_filename);
+#ifdef TRACK_SRCFILE
+ free_and_clear (&src_filename);
+#endif /* TRACK_SRCFILE */
+ free_node_references ();
+ init_insertion_stack ();
+ init_brace_stack ();
+ command_index = 0;
+ in_menu = 0;
+}
+
+init_paragraph ()
+{
+ free_and_clear (&output_paragraph);
+ output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len);
+ output_position = 0;
+ output_paragraph[0] = '\0';
+ output_paragraph_offset = 0;
+ output_column = 0;
+ paragraph_is_open = 0;
+ current_indent = 0;
+}
+
+/* Okay, we are ready to start the conversion. Call the reader on
+ some text, and fill the text as it is output. Handle commands by
+ remembering things like open braces and the current file position on a
+ stack, and when the corresponding close brace is found, you can call
+ the function with the proper arguments. */
+reader_loop ()
+{
+ int character;
+ int done = 0;
+ int dash_count = 0;
+
+ while (!done)
+ {
+ if (input_text_offset >= size_of_input_text)
+ {
+ if (filestack)
+ {
+ free (input_filename);
+#ifdef TRACK_SRCFILE
+ free (src_filename);
+#endif /* TRACK_SRCFILE */
+ free (input_text);
+ popfile ();
+ }
+ else
+ break;
+ }
+
+ character = curchar ();
+
+ if (!in_fixed_width_font &&
+ (character == '\'' || character == '`') &&
+ input_text[input_text_offset + 1] == character)
+ {
+ input_text_offset++;
+ character = '"';
+ }
+
+ if (character == '-')
+ {
+ dash_count++;
+ if (dash_count == 3 && !in_fixed_width_font)
+ {
+ input_text_offset++;
+ continue;
+ }
+ }
+ else
+ {
+ dash_count = 0;
+ }
+
+ /* If this is a whitespace character, then check to see if the line
+ is blank. If so, advance to the carriage return. */
+ if (whitespace (character))
+ {
+ register int i = input_text_offset + 1;
+
+ while (i < size_of_input_text && whitespace (input_text[i]))
+ i++;
+
+ if (i == size_of_input_text || input_text[i] == '\n')
+ {
+ if (i == size_of_input_text)
+ i--;
+
+ input_text_offset = i;
+ character = curchar ();
+ }
+ }
+
+ if (character == '\n')
+ {
+ line_number++;
+#ifdef TRACK_SRCFILE
+ src_lineno++;
+#endif /* TRACK_SRCFILE */
+ if (in_menu && input_text_offset + 1 < size_of_input_text)
+ {
+ char *glean_node_from_menu (), *tem;
+
+ /* Note that the value of TEM is discarded, since it is
+ gauranteed to be NULL when glean_node_from_menu () is
+ called with a non-zero argument. */
+ tem = glean_node_from_menu (1);
+ }
+ }
+
+ switch (character)
+ {
+ case COMMAND_PREFIX:
+ read_command ();
+ if (strcmp (command, "bye") == 0)
+ {
+ done = 1;
+ continue;
+ }
+ break;
+
+ case '{':
+
+ /* Special case. I'm not supposed to see this character by itself.
+ If I do, it means there is a syntax error in the input text.
+ Report the error here, but remember this brace on the stack so
+ you can ignore its partner. */
+
+#ifdef ALLOW_JUNK
+ warning ("Misplaced `{'");
+ add_word ("{");
+#else
+ line_error ("Misplaced `{'");
+#endif
+ remember_brace (misplaced_brace);
+
+ /* Don't advance input_text_offset since this happens in
+ remember_brace ().
+ input_text_offset++;
+ */
+ break;
+
+ case '}':
+ pop_and_call_brace ();
+ input_text_offset++;
+ break;
+
+ default:
+ add_char (character);
+ input_text_offset++;
+ }
+ }
+}
+
+/* Find the command corresponding to STRING. If the command
+ is found, return a pointer to the data structure. Otherwise
+ return (-1). */
+COMMAND *
+get_command_entry (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; CommandTable[i].name; i++)
+ if (strcmp (CommandTable[i].name, string) == 0)
+ return (&CommandTable[i]);
+
+ /* This command is not in our predefined command table. Perhaps
+ it is a user defined command. */
+ for (i = 0; i < user_command_array_len; i++)
+ if (user_command_array[i] &&
+ (strcmp (user_command_array[i]->name, string) == 0))
+ return (user_command_array[i]);
+
+ /* Nope, we never heard of this command. */
+ return ((COMMAND *) -1);
+}
+
+/* input_text_offset is right at the command prefix character.
+ Read the next token to determine what to do. */
+read_command ()
+{
+ COMMAND *entry;
+ input_text_offset++;
+ free_and_clear (&command);
+ command = read_token ();
+
+#if defined (HAVE_MACROS)
+ /* Check to see if this command is a macro. If so, execute it here. */
+ {
+ MACRO_DEF *def;
+
+ def = find_macro (command);
+
+ if (def)
+ {
+ execute_macro (def);
+ return;
+ }
+ }
+#endif /* HAVE_MACROS */
+
+ entry = get_command_entry (command);
+
+ if ((int) entry == -1)
+ {
+#ifdef ALLOW_JUNK
+ warning ("Unknown info command `%s'", command);
+ add_word_args ("\\%s", command);
+#else
+ line_error ("Unknown info command `%s'", command);
+#endif /* ALLOW_JUNK */
+ return;
+ }
+
+ if (entry->argument_in_braces)
+ remember_brace (entry->proc);
+
+ (*(entry->proc)) (START);
+}
+
+/* Return the string which invokes PROC; a pointer to a function. */
+char *
+find_proc_name (proc)
+ FUNCTION *proc;
+{
+ register int i;
+
+ for (i = 0; CommandTable[i].name; i++)
+ if (proc == CommandTable[i].proc)
+ return (CommandTable[i].name);
+ return ("NO_NAME!");
+}
+
+init_brace_stack ()
+{
+ brace_stack = (BRACE_ELEMENT *) NULL;
+}
+
+remember_brace (proc)
+ FUNCTION *proc;
+{
+ if (curchar () != '{')
+ line_error ("@%s expected `{..}'", command);
+ else
+ input_text_offset++;
+ remember_brace_1 (proc, output_paragraph_offset);
+}
+
+/* Remember the current output position here. Save PROC
+ along with it so you can call it later. */
+remember_brace_1 (proc, position)
+ FUNCTION *proc;
+ int position;
+{
+ BRACE_ELEMENT *new = (BRACE_ELEMENT *) xmalloc (sizeof (BRACE_ELEMENT));
+ new->next = brace_stack;
+ new->proc = proc;
+ new->pos = position;
+ new->line = line_number;
+#ifdef TRACK_SRCFILE
+ new->src_lineno = src_lineno;
+#endif /* TRACK_SRCFILE */
+ brace_stack = new;
+}
+
+/* Pop the top of the brace stack, and call the associated function
+ with the args END and POS. */
+pop_and_call_brace ()
+{
+ BRACE_ELEMENT *temp;
+ FUNCTION *proc;
+ int pos;
+
+ if (brace_stack == (BRACE_ELEMENT *) NULL)
+ return (line_error ("Unmatched close brace"));
+
+ pos = brace_stack->pos;
+ proc = brace_stack->proc;
+ temp = brace_stack->next;
+ free (brace_stack);
+ brace_stack = temp;
+
+ return ((*proc) (END, pos, output_paragraph_offset));
+}
+
+/* You call discard_braces () when you shouldn't have any braces on the stack.
+ I used to think that this happens for commands that don't take arguments
+ in braces, but that was wrong because of things like @code{foo @@}. So now
+ I only detect it at the beginning of nodes. */
+discard_braces ()
+{
+ int temp_line_number = line_number;
+#ifdef TRACK_SRCFILE
+ int temp_src_lineno = src_lineno;
+#endif /* TRACK_SRCFILE */
+ char *proc_name;
+
+ if (!brace_stack)
+ return;
+
+ while (brace_stack)
+ {
+ line_number = brace_stack->line;
+#ifdef TRACK_SRCFILE
+ src_lineno = brace_stack->src_lineno;
+#endif /* TRACK_SRCFILE */
+ proc_name = find_proc_name (brace_stack->proc);
+ line_error ("@%s missing close brace", proc_name);
+ line_number = temp_line_number;
+#ifdef TRACK_SRCFILE
+ src_lineno = temp_src_lineno;
+#endif /* TRACK_SRCFILE */
+ pop_and_call_brace ();
+ }
+}
+
+get_char_len (character)
+ int character;
+{
+ /* Return the printed length of the character. */
+ int len;
+
+ switch (character)
+ {
+ case '\t':
+ len = (output_column + 8) & 0xf7;
+ if (len > fill_column)
+ len = fill_column - output_column;
+ else
+ len = len - output_column;
+ break;
+
+ case '\n':
+ len = fill_column - output_column;
+ break;
+
+ default:
+ if (character < ' ')
+ len = 2;
+ else
+ len = 1;
+ }
+ return (len);
+}
+
+add_word_args (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ char buffer[1000];
+ sprintf (buffer, format, arg1, arg2, arg3, arg4, arg5);
+ add_word (buffer);
+}
+
+/* Add STRING to output_paragraph. */
+add_word (string)
+ char *string;
+{
+ while (*string)
+ add_char (*string++);
+}
+
+/* Non-zero if the last character inserted has the syntax class of NEWLINE. */
+int last_char_was_newline = 1;
+
+/* The actual last inserted character. Note that this may be something
+ other than NEWLINE even if last_char_was_newline is 1. */
+int last_inserted_character = 0;
+
+/* Non-zero means that a newline character has already been
+ inserted, so close_paragraph () should insert one less. */
+int line_already_broken = 0;
+
+/* When non-zero we have finished an insertion (see end_insertion ()) and we
+ want to ignore false continued paragraph closings. */
+int insertion_paragraph_closed = 0;
+
+/* Add the character to the current paragraph. If filling_enabled is
+ non-zero, then do filling as well. */
+add_char (character)
+ int character;
+{
+ /* If we are avoiding outputting headers, and we are currently
+ in a menu, then simply return. */
+ if (no_headers && in_menu)
+ return;
+
+ /* If we are adding a character now, then we don't have to
+ ignore close_paragraph () calls any more. */
+ if (must_start_paragraph && character != '\n')
+ {
+ must_start_paragraph = 0;
+ line_already_broken = 0; /* The line is no longer broken. */
+ if (current_indent > output_column)
+ {
+ indent (current_indent - output_column);
+ output_column = current_indent;
+ }
+ }
+
+ if (non_splitting_words && member (character, " \t\n"))
+ character = ' ' | 0x80;
+
+ insertion_paragraph_closed = 0;
+
+ switch (character)
+ {
+ case '\n':
+ if (!filling_enabled)
+ {
+ insert ('\n');
+
+ if (force_flush_right)
+ {
+ close_paragraph ();
+ /* Hack to force single blank lines out in this mode. */
+ flush_output ();
+ }
+
+ output_column = 0;
+
+ if (!no_indent && paragraph_is_open)
+ indent (output_column = current_indent);
+ break;
+ }
+ else /* CHARACTER is newline, and filling is enabled. */
+ {
+#if defined (NOTDEF)
+ if (sentence_ender (last_inserted_character))
+ {
+ insert (' ');
+ output_column++;
+ last_inserted_character = character;
+ }
+#endif /* NOTDEF */
+ }
+
+ if (last_char_was_newline)
+ {
+ close_paragraph ();
+ pending_indent = 0;
+ }
+ else
+ {
+ last_char_was_newline = 1;
+ insert (' ');
+ output_column++;
+ }
+ break;
+
+ default:
+ {
+ int len = get_char_len (character);
+
+ if ((character == ' ') && (last_char_was_newline))
+ {
+ if (!paragraph_is_open)
+ {
+ pending_indent++;
+ return;
+ }
+ }
+
+ if (!paragraph_is_open)
+ {
+ start_paragraph ();
+
+ /* If the paragraph is supposed to be indented a certain way,
+ then discard all of the pending whitespace. Otherwise, we
+ let the whitespace stay. */
+ if (!paragraph_start_indent)
+ indent (pending_indent);
+ pending_indent = 0;
+ }
+
+ if ((output_column += len) > fill_column)
+ {
+ if (filling_enabled)
+ {
+ int temp = output_paragraph_offset;
+ while (--temp > 0 && output_paragraph[temp] != '\n')
+ {
+ /* If we have found a space, we have the place to break
+ the line. */
+ if (output_paragraph[temp] == ' ')
+ {
+ output_paragraph[temp++] = '\n';
+
+ /* We have correctly broken the line where we want
+ to. What we don't want is spaces following where
+ we have decided to break the line. We get rid of
+ them. */
+ {
+ int t1 = temp;
+ while (t1 < output_paragraph_offset
+ && whitespace (output_paragraph[t1]))
+ t1++;
+
+ if (t1 != temp)
+ {
+ strncpy ((char *) &output_paragraph[temp],
+ (char *) &output_paragraph[t1],
+ (output_paragraph_offset - t1));
+ output_paragraph_offset -= (t1 - temp);
+ }
+ }
+
+ /* Filled, but now indent if that is right. */
+ if (indented_fill && current_indent)
+ {
+ int buffer_len = ((output_paragraph_offset - temp)
+ + current_indent);
+ char *temp_buffer = (char *)xmalloc (buffer_len);
+ int indentation = 0;
+
+ /* We have to shift any markers that are in
+ front of the wrap point. */
+ {
+ register BRACE_ELEMENT *stack = brace_stack;
+
+ while (stack)
+ {
+ if (stack->pos > temp)
+ stack->pos += current_indent;
+ stack = stack->next;
+ }
+ }
+
+ while (current_indent > 0 &&
+ indentation != current_indent)
+ temp_buffer[indentation++] = ' ';
+
+ strncpy ((char *) &temp_buffer[current_indent],
+ (char *) &output_paragraph[temp],
+ buffer_len - current_indent);
+
+ if (output_paragraph_offset + buffer_len
+ >= paragraph_buffer_len)
+ {
+ unsigned char *tt = xrealloc
+ (output_paragraph,
+ (paragraph_buffer_len += buffer_len));
+ output_paragraph = tt;
+ }
+ strncpy ((char *) &output_paragraph[temp],
+ temp_buffer, buffer_len);
+ output_paragraph_offset += current_indent;
+ free (temp_buffer);
+ }
+ output_column = 0;
+ while (temp < output_paragraph_offset)
+ output_column +=
+ get_char_len (output_paragraph[temp++]);
+ output_column += len;
+ break;
+ }
+ }
+ }
+ }
+ insert (character);
+ line_already_broken = 0;
+ last_char_was_newline = 0;
+ last_inserted_character = character;
+ }
+ }
+}
+
+/* Insert CHARACTER into OUTPUT_PARAGRAPH. */
+insert (character)
+ int character;
+{
+ output_paragraph[output_paragraph_offset++] = character;
+ if (output_paragraph_offset == paragraph_buffer_len)
+ {
+ output_paragraph =
+ xrealloc (output_paragraph, (paragraph_buffer_len += 100));
+ }
+}
+
+/* Remove upto COUNT characters of whitespace from the
+ the current output line. If COUNT is less than zero,
+ then remove until none left. */
+kill_self_indent (count)
+ int count;
+{
+ /* Handle infinite case first. */
+ if (count < 0)
+ {
+ output_column = 0;
+ while (output_paragraph_offset)
+ {
+ if (whitespace (output_paragraph[output_paragraph_offset - 1]))
+ output_paragraph_offset--;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while (output_paragraph_offset && count--)
+ if (whitespace (output_paragraph[output_paragraph_offset - 1]))
+ output_paragraph_offset--;
+ else
+ break;
+ }
+}
+
+/* Non-zero means do not honor calls to flush_output (). */
+static int flushing_ignored = 0;
+
+/* Prevent calls to flush_output () from having any effect. */
+inhibit_output_flushing ()
+{
+ flushing_ignored++;
+}
+
+/* Allow calls to flush_output () to write the paragraph data. */
+uninhibit_output_flushing ()
+{
+ flushing_ignored--;
+}
+
+flush_output ()
+{
+ register int i;
+
+ if (!output_paragraph_offset || flushing_ignored)
+ return;
+
+ for (i = 0; i < output_paragraph_offset; i++)
+ {
+ if (output_paragraph[i] == (unsigned char)(' ' | 0x80) ||
+ output_paragraph[i] == (unsigned char)('\t' | 0x80) ||
+ output_paragraph[i] == (unsigned char)('\n' | 0x80) ||
+ sentence_ender (UNMETA (output_paragraph[i])))
+ output_paragraph[i] &= 0x7f;
+ }
+
+ fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
+
+ output_position += output_paragraph_offset;
+ output_paragraph_offset = 0;
+}
+
+/* How to close a paragraph controlling the number of lines between
+ this one and the last one. */
+
+/* Paragraph spacing is controlled by this variable. It is the number of
+ blank lines that you wish to appear between paragraphs. A value of
+ 1 creates a single blank line between paragraphs. */
+int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
+
+/* Close the current paragraph, leaving no blank lines between them. */
+close_single_paragraph ()
+{
+ close_paragraph_with_lines (0);
+}
+
+/* Close a paragraph after an insertion has ended. */
+close_insertion_paragraph ()
+{
+ if (!insertion_paragraph_closed)
+ {
+ /* Close the current paragraph, breaking the line. */
+ close_single_paragraph ();
+
+ /* Start a new paragraph here, inserting whatever indention is correct
+ for the now current insertion level (one above the one that we are
+ ending). */
+ start_paragraph ();
+
+ /* Tell close_paragraph () that the previous line has already been
+ broken, so it should insert one less newline. */
+ line_already_broken = 1;
+
+ /* Let functions such as add_char () know that we have already found a
+ newline. */
+ ignore_blank_line ();
+ }
+ else
+ {
+ /* If the insertion paragraph is closed already, then we are seeing
+ two `@end' commands in a row. Note that the first one we saw was
+ handled in the first part of this if-then-else clause, and at that
+ time start_paragraph () was called, partially to handle the proper
+ indentation of the current line. However, the indentation level
+ may have just changed again, so we may have to outdent the current
+ line to the new indentation level. */
+ if (current_indent < output_column)
+ kill_self_indent (output_column - current_indent);
+ }
+
+ insertion_paragraph_closed = 1;
+}
+
+close_paragraph_with_lines (lines)
+ int lines;
+{
+ int old_spacing = paragraph_spacing;
+ paragraph_spacing = lines;
+ close_paragraph ();
+ paragraph_spacing = old_spacing;
+}
+
+/* Close the currently open paragraph. */
+close_paragraph ()
+{
+ register int i;
+
+ /* The insertion paragraph is no longer closed. */
+ insertion_paragraph_closed = 0;
+
+ if (paragraph_is_open && !must_start_paragraph)
+ {
+ register int tindex, c;
+
+ tindex = output_paragraph_offset;
+
+ /* Back up to last non-newline/space character, forcing all such
+ subsequent characters to be newlines. This isn't strictly
+ necessary, but a couple of functions use the presence of a newline
+ to make decisions. */
+ for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
+ {
+ c = output_paragraph[tindex];
+
+ if (c == ' '|| c == '\n')
+ output_paragraph[tindex] = '\n';
+ else
+ break;
+ }
+
+ /* All trailing whitespace is ignored. */
+ output_paragraph_offset = ++tindex;
+
+ /* Break the line if that is appropriate. */
+ if (paragraph_spacing >= 0)
+ insert ('\n');
+
+ /* Add as many blank lines as is specified in PARAGRAPH_SPACING. */
+ if (!force_flush_right)
+ {
+ for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
+ insert ('\n');
+ }
+
+ /* If we are doing flush right indentation, then do it now
+ on the paragraph (really a single line). */
+ if (force_flush_right)
+ do_flush_right_indentation ();
+
+ flush_output ();
+ paragraph_is_open = 0;
+ no_indent = 0;
+ output_column = 0;
+ }
+ ignore_blank_line ();
+}
+
+/* Make the last line just read look as if it were only a newline. */
+ignore_blank_line ()
+{
+ last_inserted_character = '\n';
+ last_char_was_newline = 1;
+}
+
+/* Align the end of the text in output_paragraph with fill_column. */
+do_flush_right_indentation ()
+{
+ char *temp;
+ int temp_len;
+
+ kill_self_indent (-1);
+
+ if (output_paragraph[0] != '\n')
+ {
+ output_paragraph[output_paragraph_offset] = '\0';
+
+ if (output_paragraph_offset < fill_column)
+ {
+ register int i;
+
+ if (fill_column >= paragraph_buffer_len)
+ output_paragraph =
+ xrealloc (output_paragraph,
+ (paragraph_buffer_len += fill_column));
+
+ temp_len = strlen ((char *)output_paragraph);
+ temp = (char *)xmalloc (temp_len + 1);
+ bcopy ((char *)output_paragraph, temp, temp_len);
+
+ for (i = 0; i < fill_column - output_paragraph_offset; i++)
+ output_paragraph[i] = ' ';
+
+ bcopy (temp, (char *)output_paragraph + i, temp_len);
+ free (temp);
+ output_paragraph_offset = fill_column;
+ }
+ }
+}
+
+/* Begin a new paragraph. */
+start_paragraph ()
+{
+ /* First close existing one. */
+ if (paragraph_is_open)
+ close_paragraph ();
+
+ /* In either case, the insertion paragraph is no longer closed. */
+ insertion_paragraph_closed = 0;
+
+ /* However, the paragraph is open! */
+ paragraph_is_open = 1;
+
+ /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
+ had to be called before we would allow any other paragraph operations
+ to have an effect. */
+ if (!must_start_paragraph)
+ {
+ int amount_to_indent = 0;
+
+ /* If doing indentation, then insert the appropriate amount. */
+ if (!no_indent)
+ {
+ if (inhibit_paragraph_indentation)
+ {
+ amount_to_indent = current_indent;
+ if (inhibit_paragraph_indentation < 0)
+ inhibit_paragraph_indentation++;
+ }
+ else if (paragraph_start_indent < 0)
+ amount_to_indent = current_indent;
+ else
+ amount_to_indent = current_indent + paragraph_start_indent;
+
+ if (amount_to_indent >= output_column)
+ {
+ amount_to_indent -= output_column;
+ indent (amount_to_indent);
+ output_column += amount_to_indent;
+ }
+ }
+ }
+ else
+ must_start_paragraph = 0;
+}
+
+/* Insert the indentation specified by AMOUNT. */
+indent (amount)
+ int amount;
+{
+ while (--amount >= 0)
+ insert (' ');
+}
+
+/* Search forward for STRING in input_text.
+ FROM says where where to start. */
+search_forward (string, from)
+ char *string;
+ int from;
+{
+ int len = strlen (string);
+
+ while (from < size_of_input_text)
+ {
+ if (strnicmp (input_text + from, string, len) == 0)
+ return (from);
+ from++;
+ }
+ return (-1);
+}
+
+/* Whoops, Unix doesn't have stricmp, or strnicmp. */
+
+/* Case independent string compare. */
+stricmp (string1, string2)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ for (;;)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+ if (!(ch1 | ch2))
+ return (0);
+
+ ch1 = coerce_to_upper (ch1);
+ ch2 = coerce_to_upper (ch2);
+
+ if (ch1 != ch2)
+ return (1);
+ }
+}
+
+/* Compare at most COUNT characters from string1 to string2. Case
+ doesn't matter. */
+strnicmp (string1, string2, count)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ while (count)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+ if (coerce_to_upper (ch1) == coerce_to_upper (ch2))
+ count--;
+ else
+ break;
+ }
+ return (count);
+}
+
+enum insertion_type { menu, quotation, lisp, smalllisp, example,
+ smallexample, display, itemize, format, enumerate, cartouche, table,
+ ftable, vtable, group, ifinfo, flushleft, flushright, ifset, ifclear, deffn,
+ defun, defmac, defspec, defvr, defvar, defopt, deftypefn,
+ deftypefun, deftypevr, deftypevar, defcv, defivar, defop, defmethod,
+ deftypemethod, deftp, bad_type };
+
+char *insertion_type_names[] = { "menu", "quotation", "lisp",
+ "smalllisp", "example", "smallexample", "display", "itemize",
+ "format", "enumerate", "cartouche", "table", "ftable", "vtable", "group",
+ "ifinfo", "flushleft", "flushright", "ifset", "ifclear", "deffn",
+ "defun", "defmac", "defspec", "defvr", "defvar", "defopt",
+ "deftypefn", "deftypefun", "deftypevr", "deftypevar", "defcv",
+ "defivar", "defop", "defmethod", "deftypemethod", "deftp",
+ "bad_type" };
+
+int insertion_level = 0;
+typedef struct istack_elt
+{
+ struct istack_elt *next;
+ char *item_function;
+ int line_number;
+#ifdef TRACK_SRCFILE
+ int src_lineno;
+#endif /* TRACK_SRCFILE */
+ int filling_enabled;
+ int indented_fill;
+ enum insertion_type insertion;
+ int inhibited;
+} INSERTION_ELT;
+
+INSERTION_ELT *insertion_stack = (INSERTION_ELT *) NULL;
+
+init_insertion_stack ()
+{
+ insertion_stack = (INSERTION_ELT *) NULL;
+}
+
+/* Return the type of the current insertion. */
+enum insertion_type
+current_insertion_type ()
+{
+ if (!insertion_level)
+ return (bad_type);
+ else
+ return (insertion_stack->insertion);
+}
+
+/* Return a pointer to the string which is the function
+ to wrap around items. */
+char *
+current_item_function ()
+{
+ if (!insertion_level)
+ return ((char *) NULL);
+ else
+ return (insertion_stack->item_function);
+}
+
+char *
+get_item_function ()
+{
+ char *item_function;
+ get_rest_of_line (&item_function);
+ backup_input_pointer ();
+ canon_white (item_function);
+ return (item_function);
+}
+
+ /* Push the state of the current insertion on the stack. */
+push_insertion (type, item_function)
+ enum insertion_type type;
+ char *item_function;
+{
+ INSERTION_ELT *new = (INSERTION_ELT *) xmalloc (sizeof (INSERTION_ELT));
+
+ new->item_function = item_function;
+ new->filling_enabled = filling_enabled;
+ new->indented_fill = indented_fill;
+ new->insertion = type;
+ new->line_number = line_number;
+#ifdef TRACK_SRCFILE
+ new->src_lineno = src_lineno;
+#endif /* TRACK_SRCFILE */
+ new->inhibited = inhibit_paragraph_indentation;
+ new->next = insertion_stack;
+ insertion_stack = new;
+ insertion_level++;
+}
+
+ /* Pop the value on top of the insertion stack into the
+ global variables. */
+pop_insertion ()
+{
+ INSERTION_ELT *temp = insertion_stack;
+
+ if (temp == (INSERTION_ELT *) NULL)
+ return;
+
+ inhibit_paragraph_indentation = temp->inhibited;
+ filling_enabled = temp->filling_enabled;
+ indented_fill = temp->indented_fill;
+ free_and_clear (&(temp->item_function));
+ insertion_stack = insertion_stack->next;
+ free (temp);
+ insertion_level--;
+}
+
+ /* Return a pointer to the print name of this
+ enumerated type. */
+char *
+insertion_type_pname (type)
+ enum insertion_type type;
+{
+ if ((int) type < (int) bad_type)
+ return (insertion_type_names[(int) type]);
+ else
+ return ("Broken-Type in insertion_type_pname");
+}
+
+/* Return the insertion_type associated with NAME.
+ If the type is not one of the known ones, return BAD_TYPE. */
+enum insertion_type
+find_type_from_name (name)
+ char *name;
+{
+ int index = 0;
+ while (index < (int) bad_type)
+ {
+ if (stricmp (name, insertion_type_names[index]) == 0)
+ return (enum insertion_type) index;
+ index++;
+ }
+ return (bad_type);
+}
+
+do_nothing ()
+{
+}
+
+int
+defun_insertion (type)
+ enum insertion_type type;
+{
+ return
+ ((type == deffn)
+ || (type == defun)
+ || (type == defmac)
+ || (type == defspec)
+ || (type == defvr)
+ || (type == defvar)
+ || (type == defopt)
+ || (type == deftypefn)
+ || (type == deftypefun)
+ || (type == deftypevr)
+ || (type == deftypevar)
+ || (type == defcv)
+ || (type == defivar)
+ || (type == defop)
+ || (type == defmethod)
+ || (type == deftypemethod)
+ || (type == deftp));
+}
+
+/* MAX_NS is the maximum nesting level for enumerations. I picked 100
+ which seemed reasonable. This doesn't control the number of items,
+ just the number of nested lists. */
+#define max_stack_depth 100
+#define ENUM_DIGITS 1
+#define ENUM_ALPHA 2
+typedef struct {
+ int enumtype;
+ int enumval;
+} DIGIT_ALPHA;
+
+DIGIT_ALPHA enumstack[max_stack_depth];
+int enumstack_offset = 0;
+int current_enumval = 1;
+int current_enumtype = ENUM_DIGITS;
+char *enumeration_arg = (char *)NULL;
+
+start_enumerating (at, type)
+ int at, type;
+{
+ if ((enumstack_offset + 1) == max_stack_depth)
+ {
+ line_error ("Enumeration stack overflow");
+ return;
+ }
+ enumstack[enumstack_offset].enumtype = current_enumtype;
+ enumstack[enumstack_offset].enumval = current_enumval;
+ enumstack_offset++;
+ current_enumval = at;
+ current_enumtype = type;
+}
+
+stop_enumerating ()
+{
+ --enumstack_offset;
+ if (enumstack_offset < 0)
+ enumstack_offset = 0;
+
+ current_enumval = enumstack[enumstack_offset].enumval;
+ current_enumtype = enumstack[enumstack_offset].enumtype;
+}
+
+/* Place a letter or digits into the output stream. */
+enumerate_item ()
+{
+ char temp[10];
+
+ if (current_enumtype == ENUM_ALPHA)
+ {
+ if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
+ {
+ current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
+ warning ("Lettering overflow, restarting at %c", current_enumval);
+ }
+ sprintf (temp, "%c. ", current_enumval);
+ }
+ else
+ sprintf (temp, "%d. ", current_enumval);
+
+ indent (output_column += (current_indent - strlen (temp)));
+ add_word (temp);
+ current_enumval++;
+}
+
+/* This is where the work for all the "insertion" style
+ commands is done. A huge switch statement handles the
+ various setups, and generic code is on both sides. */
+begin_insertion (type)
+ enum insertion_type type;
+{
+ int no_discard = 0;
+
+ if (defun_insertion (type))
+ {
+ push_insertion (type, savestring (""));
+ no_discard++;
+ }
+ else
+ push_insertion (type, get_item_function ());
+
+ switch (type)
+ {
+ case menu:
+ if (!no_headers)
+ close_paragraph ();
+
+ filling_enabled = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+
+ if (!no_headers)
+ add_word ("* Menu:\n");
+
+ in_menu++;
+ no_discard++;
+ break;
+
+ /* I think @quotation is meant to do filling.
+ If you don't want filling, then use @example. */
+ case quotation:
+ close_single_paragraph ();
+ last_char_was_newline = no_indent = 0;
+ indented_fill = filling_enabled = 1;
+ inhibit_paragraph_indentation = 1;
+ current_indent += default_indentation_increment;
+ break;
+
+ case display:
+ case example:
+ case smallexample:
+ case lisp:
+ case smalllisp:
+ /* Just like @example, but no indentation. */
+ case format:
+
+ close_single_paragraph ();
+ inhibit_paragraph_indentation = 1;
+ in_fixed_width_font++;
+ filling_enabled = 0;
+ last_char_was_newline = 0;
+
+ if (type != format)
+ current_indent += default_indentation_increment;
+
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ case itemize:
+ close_single_paragraph ();
+ current_indent += default_indentation_increment;
+ filling_enabled = indented_fill = 1;
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ inhibit_paragraph_indentation = 0;
+#else
+ inhibit_paragraph_indentation = 1;
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ /* Make things work for losers who forget the itemize syntax. */
+ if (type == itemize)
+ {
+ if (!(*insertion_stack->item_function))
+ {
+ free (insertion_stack->item_function);
+ insertion_stack->item_function = savestring ("@bullet");
+ }
+ }
+ break;
+
+ case enumerate:
+ close_single_paragraph ();
+ no_indent = 0;
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ inhibit_paragraph_indentation = 0;
+#else
+ inhibit_paragraph_indentation = 1;
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ current_indent += default_indentation_increment;
+ filling_enabled = indented_fill = 1;
+
+ if (isdigit (*enumeration_arg))
+ start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
+ else
+ start_enumerating (*enumeration_arg, ENUM_ALPHA);
+ break;
+
+ /* Does nothing special in makeinfo. */
+ case group:
+ /* Only close the paragraph if we are not inside of an @example. */
+ if (!insertion_stack->next ||
+ insertion_stack->next->insertion != example)
+ close_single_paragraph ();
+ break;
+
+ /* Insertions that are no-ops in info, but do something in TeX. */
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ case cartouche:
+ break;
+
+ case deffn:
+ case defun:
+ case defmac:
+ case defspec:
+ case defvr:
+ case defvar:
+ case defopt:
+ case deftypefn:
+ case deftypefun:
+ case deftypevr:
+ case deftypevar:
+ case defcv:
+ case defivar:
+ case defop:
+ case defmethod:
+ case deftypemethod:
+ case deftp:
+ inhibit_paragraph_indentation = 1;
+ filling_enabled = indented_fill = 1;
+ current_indent += default_indentation_increment;
+ no_indent = 0;
+ break;
+
+ case flushleft:
+ close_single_paragraph ();
+ inhibit_paragraph_indentation = 1;
+ filling_enabled = indented_fill = no_indent = 0;
+ break;
+
+ case flushright:
+ close_single_paragraph ();
+ filling_enabled = indented_fill = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+ force_flush_right++;
+ break;
+ }
+
+ if (!no_discard)
+ discard_until ("\n");
+}
+
+/* Try to end the insertion with the specified TYPE.
+ TYPE, with a value of bad_type, gets translated to match
+ the value currently on top of the stack.
+ Otherwise, if TYPE doesn't match the top of the insertion stack,
+ give error. */
+end_insertion (type)
+ enum insertion_type type;
+{
+ enum insertion_type temp_type;
+
+ if (!insertion_level)
+ return;
+
+ temp_type = current_insertion_type ();
+
+ if (type == bad_type)
+ type = temp_type;
+
+ if (type != temp_type)
+ {
+ line_error
+ ("Expected `%s', but saw `%s'.",
+ insertion_type_pname (temp_type), insertion_type_pname (type));
+ return;
+ }
+
+ pop_insertion ();
+
+ switch (type)
+ {
+ /* "Insertions which have no effect on paragraph formatting. */
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ break;
+
+ case menu:
+ in_menu--; /* No longer hacking menus. */
+ if (!no_headers)
+ close_insertion_paragraph ();
+ break;
+
+ case enumerate:
+ stop_enumerating ();
+ close_insertion_paragraph ();
+ current_indent -= default_indentation_increment;
+ break;
+
+ case flushleft:
+ case group:
+ case cartouche:
+ close_insertion_paragraph ();
+ break;
+
+ case format:
+ case display:
+ case example:
+ case smallexample:
+ case lisp:
+ case smalllisp:
+ case quotation:
+
+ /* @quotation is the only one of the above without a fixed width
+ font. */
+ if (type != quotation)
+ in_fixed_width_font--;
+
+ /* @format is the only fixed_width insertion without a change
+ in indentation. */
+ if (type != format)
+ current_indent -= default_indentation_increment;
+
+ /* The ending of one of these insertions always marks the
+ start of a new paragraph. */
+ close_insertion_paragraph ();
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ case itemize:
+ current_indent -= default_indentation_increment;
+ break;
+
+ case flushright:
+ force_flush_right--;
+ close_insertion_paragraph ();
+ break;
+
+ /* Handle the @defun style insertions with a default clause. */
+ default:
+ current_indent -= default_indentation_increment;
+ close_insertion_paragraph ();
+ break;
+ }
+}
+
+/* Insertions cannot cross certain boundaries, such as node beginnings. In
+ code that creates such boundaries, you should call discard_insertions ()
+ before doing anything else. It prints the errors for you, and cleans up
+ the insertion stack. */
+discard_insertions ()
+{
+ int real_line_number = line_number;
+#ifdef TRACK_SRCFILE
+ int real_src_lineno = src_lineno;
+#endif /* TRACK_SRCFILE */
+ while (insertion_stack)
+ {
+ if (insertion_stack->insertion == ifinfo ||
+ insertion_stack->insertion == ifset ||
+ insertion_stack->insertion == ifclear ||
+ insertion_stack->insertion == cartouche)
+ break;
+ else
+ {
+ char *offender = (char *)
+ insertion_type_pname (insertion_stack->insertion);
+
+ line_number = insertion_stack->line_number;
+#ifdef TRACK_SRCFILE
+ src_lineno = insertion_stack->src_lineno;
+#endif /* TRACK_SRCFILE */
+ line_error ("This `%s' doesn't have a matching `%cend %s'", offender,
+ COMMAND_PREFIX, offender);
+ pop_insertion ();
+ }
+ }
+ line_number = real_line_number;
+#ifdef TRACK_SRCFILE
+ src_lineno = real_src_lineno;
+#endif /* TRACK_SRCFILE */
+
+}
+
+/* The actual commands themselves. */
+
+/* Commands which insert themselves. */
+insert_self ()
+{
+ add_word (command);
+}
+
+/* Force a line break in the output. */
+cm_asterisk ()
+{
+ close_single_paragraph ();
+#if !defined (ASTERISK_NEW_PARAGRAPH)
+ cm_noindent ();
+#endif /* ASTERISK_NEW_PARAGRAPH */
+}
+
+/* Insert ellipsis. */
+cm_dots (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("...");
+}
+
+cm_bullet (arg)
+ int arg;
+{
+ if (arg == START)
+ add_char ('*');
+}
+
+cm_minus (arg)
+ int arg;
+{
+ if (arg == START)
+ add_char ('-');
+}
+
+/* Insert "TeX". */
+cm_TeX (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("TeX");
+}
+
+cm_copyright (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("(C)");
+}
+
+cm_today (arg)
+ int arg;
+{
+ static char * months [12] =
+ { "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December" };
+ if (arg == START)
+ {
+/*partain: long timer = (time (0)); */
+ time_t timer = (time (0));
+ struct tm * ts = (localtime (&timer));
+ add_word_args
+ ("%d %s %d",
+ (ts -> tm_mday),
+ (months [ts -> tm_mon]),
+ ((ts -> tm_year) + 1900));
+ }
+}
+
+cm_code (arg)
+ int arg;
+{
+ extern int printing_index;
+
+ if (printing_index)
+ return;
+
+ if (arg == START)
+ {
+ in_fixed_width_font++;
+ add_char ('`');
+ }
+ else
+ {
+ add_word ("'");
+ in_fixed_width_font--;
+ }
+}
+
+cm_samp (arg)
+ int arg;
+{
+ cm_code (arg);
+}
+
+cm_file (arg)
+ int arg;
+{
+ cm_code (arg);
+}
+
+cm_kbd (arg)
+ int arg;
+{
+ cm_code (arg);
+}
+
+cm_key (arg)
+ int arg;
+{
+}
+
+/* Convert the character at position into CTL. */
+cm_ctrl (arg, position)
+ int arg, position;
+{
+ if (arg == END)
+ output_paragraph[position - 1] = CTL (output_paragraph[position]);
+}
+
+/* Small Caps in makeinfo just does all caps. */
+cm_sc (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ if (arg == END)
+ {
+ while (start_pos < end_pos)
+ {
+ output_paragraph[start_pos] =
+ coerce_to_upper (output_paragraph[start_pos]);
+ start_pos++;
+ }
+ }
+}
+
+/* @var in makeinfo just uppercases the text. */
+cm_var (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ if (arg == END)
+ {
+ while (start_pos < end_pos)
+ {
+ output_paragraph[start_pos] =
+ coerce_to_upper (output_paragraph[start_pos]);
+ start_pos++;
+ }
+ }
+}
+
+cm_dfn (arg, position)
+ int arg, position;
+{
+ add_char ('"');
+}
+
+cm_emph (arg)
+ int arg;
+{
+ add_char ('*');
+}
+
+cm_strong (arg, position)
+ int arg, position;
+{
+ cm_emph (arg);
+}
+
+cm_cite (arg, position)
+ int arg, position;
+{
+ if (arg == START)
+ add_word ("`");
+ else
+ add_word ("'");
+}
+
+/* Current text is italicized. */
+cm_italic (arg, start, end)
+ int arg, start, end;
+{
+}
+
+/* Current text is highlighted. */
+cm_bold (arg, start, end)
+ int arg, start, end;
+{
+ cm_italic (arg);
+}
+
+/* Current text is in roman font. */
+cm_roman (arg, start, end)
+ int arg, start, end;
+{
+}
+
+/* Current text is in roman font. */
+cm_titlefont (arg, start, end)
+ int arg, start, end;
+{
+}
+
+/* Italicize titles. */
+cm_title (arg, start, end)
+ int arg, start, end;
+{
+ cm_italic (arg);
+}
+
+/* @refill is a NOP. */
+cm_refill ()
+{
+}
+
+/* Prevent the argument from being split across two lines. */
+cm_w (arg, start, end)
+ int arg, start, end;
+{
+ if (arg == START)
+ non_splitting_words++;
+ else
+ non_splitting_words--;
+}
+
+
+/* Explain that this command is obsolete, thus the user shouldn't
+ do anything with it. */
+cm_obsolete (arg, start, end)
+ int arg, start, end;
+{
+ if (arg == START)
+ warning ("The command `@%s' is obsolete", command);
+}
+
+/* Insert the text following input_text_offset up to the end of the line
+ in a new, separate paragraph. Directly underneath it, insert a
+ line of WITH_CHAR, the same length of the inserted text. */
+insert_and_underscore (with_char)
+ int with_char;
+{
+ int len, i, old_no_indent;
+ char *temp;
+
+ close_paragraph ();
+ filling_enabled = indented_fill = 0;
+ old_no_indent = no_indent;
+ no_indent = 1;
+ get_rest_of_line (&temp);
+
+ len = output_position;
+ execute_string ("%s\n", temp);
+ free (temp);
+
+ len = ((output_position + output_paragraph_offset) - 1) - len;
+ for (i = 0; i < len; i++)
+ add_char (with_char);
+ insert ('\n');
+ close_paragraph ();
+ filling_enabled = 1;
+ no_indent = old_no_indent;
+}
+
+/* The remainder of the text on this line is a chapter heading. */
+cm_chapter ()
+{
+ insert_and_underscore ('*');
+}
+
+/* The remainder of the text on this line is a section heading. */
+cm_section ()
+{
+ insert_and_underscore ('=');
+}
+
+/* The remainder of the text on this line is a subsection heading. */
+cm_subsection ()
+{
+ insert_and_underscore ('-');
+}
+
+/* The remainder of the text on this line is a subsubsection heading. */
+cm_subsubsection ()
+{
+ insert_and_underscore ('.');
+}
+
+/* Here is a structure which associates sectioning commands with
+ an integer, hopefully to reflect the `depth' of the current
+ section. */
+struct {
+ char *name;
+ int level;
+} section_alist[] = {
+ { "unnumberedsubsubsec", 5 },
+ { "unnumberedsubsec", 4 },
+ { "unnumberedsec", 3 },
+ { "unnumbered", 2 },
+ { "appendixsubsubsec", 5 },
+ { "appendixsubsec", 4 },
+ { "appendixsec", 3 },
+ { "appendixsection", 3 },
+ { "appendix", 2 },
+ { "subsubsec", 5 },
+ { "subsubsection", 5 },
+ { "subsection", 4 },
+ { "section", 3 },
+ { "chapter", 2 },
+ { "top", 1 },
+
+ { (char *)NULL, 0 }
+};
+
+/* Return an integer which identifies the type section present in TEXT. */
+int
+what_section (text)
+ char *text;
+{
+ register int i, j;
+ char *t;
+
+ find_section_command:
+ for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
+ if (text[j] != '@')
+ return (-1);
+
+ text = text + j + 1;
+
+ /* We skip @comment commands. */
+ if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
+ (strncmp (text, "c ", strlen ("c ")) == 0))
+ {
+ while (*text++ != '\n');
+ goto find_section_command;
+ }
+
+ /* Handle italicized sectioning commands. */
+ if (*text == 'i')
+ text++;
+
+ for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
+
+ for (i = 0; t = section_alist[i].name; i++)
+ {
+ if (j == strlen (t) && strncmp (t, text, j) == 0)
+ return (section_alist[i].level);
+ }
+ return (-1);
+}
+
+/* Treat this just like @unnumbered. The only difference is
+ in node defaulting. */
+cm_top ()
+{
+ static int top_encountered = 0;
+ cm_unnumbered ();
+
+ /* It is an error to have more than one @top. */
+ if (top_encountered)
+ {
+ TAG_ENTRY *tag = tag_table;
+
+ line_error ("There already is a node having @top as a section");
+
+ while (tag != (TAG_ENTRY *)NULL)
+ {
+ if ((tag->flags & IS_TOP))
+ {
+ int old_line_number = line_number;
+ line_number = tag->line_no;
+ line_error ("Here is the @top node.");
+ line_number = old_line_number;
+ return;
+ }
+ tag = tag->next_ent;
+ }
+ }
+ else
+ {
+ top_encountered = 1;
+
+ /* The most recently defined node is the top node. */
+ if (tag_table)
+ tag_table->flags |= IS_TOP;
+
+ /* Now set the logical hierarchical level of the Top node. */
+ {
+ int orig_offset = input_text_offset;
+
+ input_text_offset = search_forward ("\n@node", orig_offset);
+
+ if (input_text_offset > 0)
+ {
+ int this_section;
+
+ /* Move to the end of this line, and find out what the
+ sectioning command is here. */
+ while (input_text[input_text_offset] != '\n')
+ input_text_offset++;
+
+ if (input_text_offset < size_of_input_text)
+ input_text_offset++;
+
+ this_section = what_section (input_text + input_text_offset);
+
+ /* If we found a sectioning command, then give the top section
+ a level of this section - 1. */
+ if (this_section != -1)
+ {
+ register int i;
+
+ for (i = 0; section_alist[i].name; i++)
+ if (strcmp (section_alist[i].name, "Top") == 0)
+ {
+ section_alist[i].level = this_section - 1;
+ break;
+ }
+ }
+ }
+ input_text_offset = orig_offset;
+ }
+ }
+}
+
+/* The remainder of the text on this line is an unnumbered heading. */
+cm_unnumbered ()
+{
+ cm_chapter ();
+}
+
+/* The remainder of the text on this line is an unnumbered section heading. */
+cm_unnumberedsec ()
+{
+ cm_section ();
+}
+
+/* The remainder of the text on this line is an unnumbered
+ subsection heading. */
+cm_unnumberedsubsec ()
+{
+ cm_subsection ();
+}
+
+/* The remainder of the text on this line is an unnumbered
+ subsubsection heading. */
+cm_unnumberedsubsubsec ()
+{
+ cm_subsubsection ();
+}
+
+/* The remainder of the text on this line is an appendix heading. */
+cm_appendix ()
+{
+ cm_chapter ();
+}
+
+/* The remainder of the text on this line is an appendix section heading. */
+cm_appendixsec ()
+{
+ cm_section ();
+}
+
+/* The remainder of the text on this line is an appendix subsection heading. */
+cm_appendixsubsec ()
+{
+ cm_subsection ();
+}
+
+/* The remainder of the text on this line is an appendix
+ subsubsection heading. */
+cm_appendixsubsubsec ()
+{
+ cm_subsubsection ();
+}
+
+/* Compatibility functions substitute for chapter, section, etc. */
+cm_majorheading ()
+{
+ cm_chapheading ();
+}
+
+cm_chapheading ()
+{
+ cm_chapter ();
+}
+
+cm_heading ()
+{
+ cm_section ();
+}
+
+cm_subheading ()
+{
+ cm_subsection ();
+}
+
+cm_subsubheading ()
+{
+ cm_subsubsection ();
+}
+
+
+/* **************************************************************** */
+/* */
+/* Adding nodes, and making tags */
+/* */
+/* **************************************************************** */
+
+/* Start a new tag table. */
+init_tag_table ()
+{
+ while (tag_table != (TAG_ENTRY *) NULL)
+ {
+ TAG_ENTRY *temp = tag_table;
+ free (temp->node);
+ free (temp->prev);
+ free (temp->next);
+ free (temp->up);
+ tag_table = tag_table->next_ent;
+ free (temp);
+ }
+}
+
+write_tag_table ()
+{
+ return (write_tag_table_internal (0)); /* Not indirect. */
+}
+
+write_tag_table_indirect ()
+{
+ return (write_tag_table_internal (1));
+}
+
+/* Write out the contents of the existing tag table.
+ INDIRECT_P says how to format the output. */
+write_tag_table_internal (indirect_p)
+ int indirect_p;
+{
+ TAG_ENTRY *node = tag_table;
+ int old_indent = no_indent;
+
+ no_indent = 1;
+ filling_enabled = 0;
+ must_start_paragraph = 0;
+ close_paragraph ();
+
+ if (!indirect_p)
+ {
+ no_indent = 1;
+ insert ('\n');
+ }
+
+ add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
+
+ while (node != (TAG_ENTRY *) NULL)
+ {
+ add_word_args ("Node: %s\177%d\n", node->node, node->position);
+ node = node->next_ent;
+ }
+
+ add_word ("\037\nEnd Tag Table\n");
+ flush_output ();
+ no_indent = old_indent;
+}
+
+char *
+get_node_token ()
+{
+ char *string;
+
+ get_until_in_line (",", &string);
+
+ if (curchar () == ',')
+ input_text_offset++;
+
+ canon_white (string);
+
+ /* Allow things like @@nodename. */
+ normalize_node_name (string);
+
+ return (string);
+}
+
+/* Given a node name in STRING, remove double @ signs, replacing them
+ with just one. */
+normalize_node_name (string)
+ char *string;
+{
+ register int i, l = strlen (string);
+
+ for (i = 0; i < l; i++)
+ {
+ if (string[i] == '@' && string[i + 1] == '@')
+ {
+ strncpy (string + i, string + i + 1, l - i);
+ l--;
+ }
+ }
+}
+
+/* Look up NAME in the tag table, and return the associated
+ tag_entry. If the node is not in the table return NULL. */
+TAG_ENTRY *
+find_node (name)
+ char *name;
+{
+ TAG_ENTRY *tag = tag_table;
+
+ while (tag != (TAG_ENTRY *) NULL)
+ {
+ if (stricmp (tag->node, name) == 0)
+ return (tag);
+ tag = tag->next_ent;
+ }
+ return ((TAG_ENTRY *) NULL);
+}
+
+/* Remember NODE and associates. */
+#ifdef TRACK_SRCFILE
+remember_node (node, prev, next, up, position, line_no, src_line_no, no_warn)
+ int src_line_no;
+#else
+remember_node (node, prev, next, up, position, line_no, no_warn)
+#endif /* TRACK_SRCFILE */
+ char *node, *prev, *next, *up;
+ int position, line_no, no_warn;
+{
+ /* Check for existence of this tag already. */
+ if (validating)
+ {
+ register TAG_ENTRY *tag = find_node (node);
+ if (tag)
+ {
+ line_error ("Node `%s' multiply defined (%d is first definition)",
+ node, tag->line_no);
+ return;
+ }
+ }
+
+ /* First, make this the current node. */
+ current_node = node;
+
+ /* Now add it to the list. */
+ {
+ TAG_ENTRY *new = (TAG_ENTRY *) xmalloc (sizeof (TAG_ENTRY));
+ new->node = node;
+ new->prev = prev;
+ new->next = next;
+ new->up = up;
+ new->position = position;
+ new->line_no = line_no;
+ new->filename = node_filename;
+#ifdef TRACK_SRCFILE
+ new->src_lineno = src_line_no;
+ new->src_filename = node_src_filename;
+#endif /* TRACK_SRCFILE */
+ new->touched = 0; /* not yet referenced. */
+ new->flags = 0;
+ if (no_warn)
+ new->flags |= NO_WARN;
+ new->next_ent = tag_table;
+ tag_table = new;
+ }
+}
+
+/* The order is: nodename, nextnode, prevnode, upnode.
+ If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
+ You must follow a node command which has those fields defaulted
+ with a sectioning command (e.g. @chapter) giving the "level" of that node.
+ It is an error not to do so.
+ The defaults come from the menu in this nodes parent. */
+cm_node ()
+{
+ char *node, *prev, *next, *up;
+ int new_node_pos, defaulting, this_section, no_warn = 0;
+ extern int already_outputting_pending_notes;
+
+ if (strcmp (command, "nwnode") == 0)
+ no_warn = 1;
+
+ /* Get rid of unmatched brace arguments from previous commands. */
+ discard_braces ();
+
+ /* There also might be insertions left lying around that haven't been
+ ended yet. Do that also. */
+ discard_insertions ();
+
+ if (!already_outputting_pending_notes)
+ {
+ close_paragraph ();
+ output_pending_notes ();
+ free_pending_notes ();
+ }
+
+ filling_enabled = indented_fill = 0;
+ new_node_pos = output_position + 1;
+ current_footnote_number = 1;
+
+ node = get_node_token ();
+ next = get_node_token ();
+ prev = get_node_token ();
+ up = get_node_token ();
+
+ no_indent = 1;
+ if (!no_headers)
+ add_word_args ("\037\nFile: %s, Node: %s", pretty_output_filename, node);
+
+ /* Check for defaulting of this node's next, prev, and up fields. */
+ defaulting = ((strlen (next) == 0) &&
+ (strlen (prev) == 0) &&
+ (strlen (up) == 0));
+
+ this_section = what_section (input_text + input_text_offset);
+
+ /* If we are defaulting, then look at the immediately following
+ sectioning command (error if none) to determine the node's
+ level. Find the node that contains the menu mentioning this node
+ that is one level up (error if not found). That node is the "Up"
+ of this node. Default the "Next" and "Prev" from the menu. */
+ if (defaulting)
+ {
+ NODE_REF *last_ref = (NODE_REF *)NULL;
+ NODE_REF *ref = node_references;
+
+ if (this_section < 0)
+ {
+ char *polite_section_name = "top";
+ int i;
+
+ for (i = 0; section_alist[i].name; i++)
+ if (section_alist[i].level == current_section + 1)
+ {
+ polite_section_name = section_alist[i].name;
+ break;
+ }
+
+ line_error
+ ("Node `%s' requires a sectioning command (e.g. @%s)",
+ node, polite_section_name);
+ }
+ else
+ {
+ if (stricmp (node, "Top") == 0)
+ {
+ /* Default the NEXT pointer to be the first menu item in
+ this node, if there is a menu in this node. */
+ {
+ int orig_offset, orig_size;
+ char *glean_node_from_menu ();
+
+ orig_offset = input_text_offset;
+ orig_size = search_forward ("\n@node ", orig_offset);
+
+ if (orig_size < 0)
+ orig_size = size_of_input_text;
+
+ input_text_offset = search_forward ("\n@menu", orig_offset);
+ if (input_text_offset > -1)
+ {
+ input_text_offset =
+ search_forward ("\n* ", input_text_offset);
+
+ if (input_text_offset > -1)
+ next = glean_node_from_menu (0);
+
+ if (next)
+ {
+ prev = savestring ("(DIR)");
+ up = savestring ("(DIR)");
+ }
+ }
+ input_text_offset = orig_offset;
+ }
+ }
+
+ while (ref)
+ {
+ if (ref->section == (this_section - 1) &&
+ ref->type == menu_reference &&
+ stricmp (ref->node, node) == 0)
+ {
+ char *containing_node = ref->containing_node;
+
+ free (up);
+ up = savestring (containing_node);
+
+ if (last_ref && last_ref->type == menu_reference &&
+ strcmp
+ (last_ref->containing_node, containing_node) == 0)
+ {
+ free (next);
+ next = savestring (last_ref->node);
+ }
+
+ while ((ref->section == this_section - 1) &&
+ (ref->next) &&
+ (ref->next->type != menu_reference))
+ ref = ref->next;
+
+ if (ref->next && ref->type == menu_reference &&
+ strcmp
+ (ref->next->containing_node, containing_node) == 0)
+ {
+ free (prev);
+ prev = savestring (ref->next->node);
+ }
+ else if (!ref->next &&
+ stricmp (ref->containing_node, "Top") == 0)
+ {
+ free (prev);
+ prev = savestring (ref->containing_node);
+ }
+ break;
+ }
+ last_ref = ref;
+ ref = ref->next;
+ }
+ }
+ }
+
+ if (!no_headers)
+ {
+ if (*next)
+ add_word_args (", Next: %s", next);
+
+ if (*prev)
+ add_word_args (", Prev: %s", prev);
+
+ if (*up)
+ add_word_args (", Up: %s", up);
+ }
+
+ insert ('\n');
+ close_paragraph ();
+ no_indent = 0;
+
+ if (!*node)
+ {
+ line_error ("No node name specified for `@%s' command", command);
+ free (node);
+ free (next);
+ free (prev);
+ free (up);
+ }
+ else
+ {
+ if (!*next) { free (next); next = (char *)NULL; }
+ if (!*prev) { free (prev); prev = (char *)NULL; }
+ if (!*up) { free (up); up = (char *)NULL; }
+#ifdef TRACK_SRCFILE
+ remember_node (node, prev, next, up, new_node_pos, line_number, src_lineno, no_warn);
+#else
+ remember_node (node, prev, next, up, new_node_pos, line_number, no_warn);
+#endif /* TRACK_SRCFILE */
+ }
+
+ /* Change the section only if there was a sectioning command. */
+ if (this_section >= 0)
+ current_section = this_section;
+
+ filling_enabled = 1;
+}
+
+/* Validation of an info file.
+ Scan through the list of tag entrys touching the Prev, Next, and Up
+ elements of each. It is an error not to be able to touch one of them,
+ except in the case of external node references, such as "(DIR)".
+
+ If the Prev is different from the Up,
+ then the Prev node must have a Next pointing at this node.
+
+ Every node except Top must have an Up.
+ The Up node must contain some sort of reference, other than a Next,
+ to this node.
+
+ If the Next is different from the Next of the Up,
+ then the Next node must have a Prev pointing at this node. */
+validate_file (filename, tag_table)
+ char *filename;
+ TAG_ENTRY *tag_table;
+{
+ char *old_input_filename = input_filename;
+#ifdef TRACK_SRCFILE
+ char *old_src_filename = src_filename;
+#endif /* TRACK_SRCFILE */
+ TAG_ENTRY *tags = tag_table;
+
+ while (tags != (TAG_ENTRY *) NULL)
+ {
+ register TAG_ENTRY *temp_tag;
+
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+#ifdef TRACK_SRCFILE
+ src_filename = tags->src_filename;
+ src_lineno = tags->src_lineno;
+#endif /* TRACK_SRCFILE */
+
+ /* If this node has a Next, then make sure that the Next exists. */
+ if (tags->next)
+ {
+#ifdef TRACK_SRCFILE
+ validate (tags->next, tags->line_no, tags->src_lineno, "Next");
+#else
+ validate (tags->next, tags->line_no, "Next");
+#endif /* TRACK_SRCFILE */
+
+ /* If the Next node exists, and there is no Up, then make
+ sure that the Prev of the Next points back. */
+ if (temp_tag = find_node (tags->next))
+ {
+ char *prev = temp_tag->prev;
+ if (!prev || (stricmp (prev, tags->node) != 0))
+ {
+ line_error
+ ("Node `%s''s Next field not pointed back to", tags->node);
+ line_number = temp_tag->line_no;
+ input_filename = temp_tag->filename;
+#ifdef TRACK_SRCFILE
+ src_lineno = temp_tag->src_lineno;
+ src_filename = temp_tag->src_filename;
+#endif /* TRACK_SRCFILE */
+ line_error
+ ("This node (`%s') is the one with the bad `Prev'",
+ temp_tag->node);
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+#ifdef TRACK_SRCFILE
+ src_lineno = tags->src_lineno;
+ src_filename = tags->src_filename;
+#endif /* TRACK_SRCFILE */
+ temp_tag->flags |= PREV_ERROR;
+ }
+ }
+ }
+
+ /* Validate the Prev field if there is one, and we haven't already
+ complained about it in some way. You don't have to have a Prev
+ field at this stage. */
+ if (!(tags->flags & PREV_ERROR) && tags->prev)
+ {
+#ifdef TRACK_SRCFILE
+ int valid = validate (tags->prev, tags->line_no, tags->src_lineno, "Prev");
+#else
+ int valid = validate (tags->prev, tags->line_no, "Prev");
+#endif /* TRACK_SRCFILE */
+
+ if (!valid)
+ tags->flags |= PREV_ERROR;
+ else
+ {
+ /* If the Prev field is not the same as the Up field,
+ then the node pointed to by the Prev field must have
+ a Next field which points to this node. */
+ if (tags->up && (stricmp (tags->prev, tags->up) != 0))
+ {
+ temp_tag = find_node (tags->prev);
+ if (!temp_tag->next ||
+ (stricmp (temp_tag->next, tags->node) != 0))
+ {
+ line_error ("Node `%s''s Prev field not pointed back to",
+ tags->node);
+ line_number = temp_tag->line_no;
+ input_filename = temp_tag->filename;
+#ifdef TRACK_SRCFILE
+ src_filename = temp_tag->src_filename;
+ src_lineno = temp_tag->src_lineno;
+#endif /* TRACK_SRCFILE */
+ line_error
+ ("This node (`%s') is the one with the bad `Next'",
+ temp_tag->node);
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+#ifdef TRACK_SRCFILE
+ src_filename = tags->src_filename;
+ src_lineno = tags->src_lineno;
+#endif /* TRACK_SRCFILE */
+ temp_tag->flags |= NEXT_ERROR;
+ }
+ }
+ }
+ }
+
+ if (!tags->up && (stricmp (tags->node, "Top") != 0))
+ line_error ("Node `%s' is missing an \"Up\" field", tags->node);
+ else if (tags->up)
+ {
+#ifdef TRACK_SRCFILE
+ int valid = validate (tags->up, tags->line_no, tags->src_lineno, "Up");
+#else
+ int valid = validate (tags->up, tags->line_no, "Up");
+#endif /* TRACK_SRCFILE */
+
+ /* If node X has Up: Y, then warn if Y fails to have a menu item
+ or note pointing at X, if Y isn't of the form "(Y)". */
+ if (valid && *tags->up != '(')
+ {
+ NODE_REF *nref, *tref, *list;
+ NODE_REF *find_node_reference ();
+
+ tref = (NODE_REF *) NULL;
+ list = node_references;
+
+ for (;;)
+ {
+ if (!(nref = find_node_reference (tags->node, list)))
+ break;
+
+ if (stricmp (nref->containing_node, tags->up) == 0)
+ {
+ if (nref->type != menu_reference)
+ {
+ tref = nref;
+ list = nref->next;
+ }
+ else
+ break;
+ }
+ list = nref->next;
+ }
+
+ if (!nref)
+ {
+ temp_tag = find_node (tags->up);
+ line_number = temp_tag->line_no;
+ filename = temp_tag->filename;
+#ifdef TRACK_SRCFILE
+ src_filename = temp_tag->src_filename;
+ src_lineno = temp_tag->src_lineno;
+#endif /* TRACK_SRCFILE */
+ if (!tref)
+ line_error (
+"`%s' has an Up field of `%s', but `%s' has no menu item for `%s'",
+ tags->node, tags->up, tags->up, tags->node);
+ line_number = tags->line_no;
+ filename = tags->filename;
+#ifdef TRACK_SRCFILE
+ src_filename = tags->src_filename;
+ src_lineno = tags->src_lineno;
+#endif /* TRACK_SRCFILE */
+ }
+ }
+ }
+ tags = tags->next_ent;
+ }
+
+ validate_other_references (node_references);
+ /* We have told the user about the references which didn't exist.
+ Now tell him about the nodes which aren't referenced. */
+
+ tags = tag_table;
+ while (tags != (TAG_ENTRY *) NULL)
+ {
+ /* Special hack. If the node in question appears to have
+ been referenced more than REFERENCE_WARNING_LIMIT times,
+ give a warning. */
+ if (tags->touched > reference_warning_limit)
+ {
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+#ifdef TRACK_SRCFILE
+ src_filename = tags->src_filename;
+ src_lineno = tags->src_lineno;
+#endif /* TRACK_SRCFILE */
+ warning ("Node `%s' has been referenced %d times",
+ tags->node, tags->touched);
+ }
+
+ if (tags->touched == 0)
+ {
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+#ifdef TRACK_SRCFILE
+ src_filename = tags->src_filename;
+ src_lineno = tags->src_lineno;
+#endif /* TRACK_SRCFILE */
+
+ /* Notice that the node "Top" is special, and doesn't have to
+ be referenced. */
+ if (stricmp (tags->node, "Top") != 0)
+ warning ("Unreferenced node `%s'", tags->node);
+ }
+ tags = tags->next_ent;
+ }
+ input_filename = old_input_filename;
+#ifdef TRACK_SRCFILE
+ src_filename = old_src_filename;
+#endif /* TRACK_SRCFILE */
+}
+
+/* Return 1 if tag correctly validated, or 0 if not. */
+#ifdef TRACK_SRCFILE
+validate (tag, line, src_line, label)
+#else
+validate (tag, line, label)
+#endif /* TRACK_SRCFILE */
+ char *tag;
+ int line;
+#ifdef TRACK_SRCFILE
+ int src_line;
+#endif /* TRACK_SRCFILE */
+ char *label;
+{
+ TAG_ENTRY *result;
+
+ /* If there isn't a tag to verify, or if the tag is in another file,
+ then it must be okay. */
+ if (!tag || !*tag || *tag == '(')
+ return (1);
+
+ /* Otherwise, the tag must exist. */
+ result = find_node (tag);
+
+ if (!result)
+ {
+ line_number = line;
+#ifdef TRACK_SRCFILE
+ src_lineno = src_line;
+#endif /* TRACK_SRCFILE */
+ line_error (
+"Validation error. `%s' field points to node `%s', which doesn't exist",
+ label, tag);
+ return (0);
+ }
+ result->touched++;
+ return (1);
+}
+
+/* Split large output files into a series of smaller files. Each file
+ is pointed to in the tag table, which then gets written out as the
+ original file. The new files have the same name as the original file
+ with a "-num" attached. SIZE is the largest number of bytes to allow
+ in any single split file. */
+split_file (filename, size)
+ char *filename;
+ int size;
+{
+ char *root_filename, *root_pathname;
+ char *the_file, *filename_part ();
+ struct stat fileinfo;
+ char *the_header;
+ int header_size;
+
+ /* Can only do this to files with tag tables. */
+ if (!tag_table)
+ return;
+
+ if (size == 0)
+ size = DEFAULT_SPLIT_SIZE;
+
+ if ((stat (filename, &fileinfo) != 0) ||
+ (fileinfo.st_size < SPLIT_SIZE_THRESHOLD))
+ return;
+
+ the_file = find_and_load (filename);
+ if (!the_file)
+ return;
+
+ root_filename = filename_part (filename);
+ root_pathname = pathname_part (filename);
+
+ if (!root_pathname)
+ root_pathname = savestring ("");
+
+ /* Start splitting the file. Walk along the tag table
+ outputting sections of the file. When we have written
+ all of the nodes in the tag table, make the top-level
+ pointer file, which contains indirect pointers and
+ tags for the nodes. */
+ {
+ int which_file = 1;
+ TAG_ENTRY *tags = tag_table;
+ char *indirect_info = (char *)NULL;
+
+ /* Remember the `header' of this file. The first tag in the file is
+ the bottom of the header; the top of the file is the start. */
+ the_header = (char *)xmalloc (1 + (header_size = (tags->position - 2)));
+ bcopy (the_file, the_header, header_size);
+
+ while (tags)
+ {
+ int file_top, file_bot, limit;
+
+ /* Have to include the Control-_. */
+ file_top = file_bot = tags->position - 2;
+ limit = file_top + size;
+
+ /* If the rest of this file is only one node, then
+ that is the entire subfile. */
+ if (!tags->next_ent)
+ {
+ int i = tags->position + 1;
+ char last_char = the_file[i];
+
+ while (i < fileinfo.st_size)
+ {
+ if ((the_file[i] == '\037') &&
+ ((last_char == '\n') ||
+ (last_char == '\014')))
+ break;
+ else
+ last_char = the_file[i];
+ i++;
+ }
+ file_bot = i;
+ tags = tags->next_ent;
+ goto write_region;
+ }
+
+ /* Otherwise, find the largest number of nodes that can fit in
+ this subfile. */
+ for (; tags; tags = tags->next_ent)
+ {
+ if (!tags->next_ent)
+ {
+ /* This entry is the last node. Search forward for the end
+ of this node, and that is the end of this file. */
+ int i = tags->position + 1;
+ char last_char = the_file[i];
+
+ while (i < fileinfo.st_size)
+ {
+ if ((the_file[i] == '\037') &&
+ ((last_char == '\n') ||
+ (last_char == '\014')))
+ break;
+ else
+ last_char = the_file[i];
+ i++;
+ }
+ file_bot = i;
+
+ if (file_bot < limit)
+ {
+ tags = tags->next_ent;
+ goto write_region;
+ }
+ else
+ {
+ /* Here we want to write out everything before the last
+ node, and then write the last node out in a file
+ by itself. */
+ file_bot = tags->position;
+ goto write_region;
+ }
+ }
+
+ if (tags->next_ent->position > limit)
+ {
+ if ((tags->position) - 2 == file_top)
+ tags = tags->next_ent;
+ file_bot = tags->position;
+ write_region:
+ {
+ int fd;
+ char *split_file = (char *)
+ xmalloc (10
+ + strlen (root_pathname)
+ + strlen (root_filename));
+ sprintf (split_file,
+ "%s%s-%d", root_pathname, root_filename, which_file);
+
+ if (((fd = open (split_file, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0)
+ || (write (fd, the_header, header_size) != header_size)
+ || (write (fd, the_file + file_top, file_bot - file_top)
+ != (file_bot - file_top))
+ || ((close (fd)) < 0))
+ {
+ perror (split_file);
+ close (fd);
+ exit (FATAL);
+ }
+
+ if (!indirect_info)
+ {
+ indirect_info = the_file + file_top;
+ sprintf (indirect_info, "\037\nIndirect:\n");
+ indirect_info += strlen (indirect_info);
+ }
+
+ sprintf (indirect_info, "%s-%d: %d\n",
+ root_filename, which_file, file_top);
+
+ free (split_file);
+ indirect_info += strlen (indirect_info);
+ which_file++;
+ break;
+ }
+ }
+ }
+ }
+
+ /* We have sucessfully created the subfiles. Now write out the
+ original again. We must use `output_stream', or
+ write_tag_table_indirect () won't know where to place the output. */
+ output_stream = fopen (filename, "w");
+ if (!output_stream)
+ {
+ perror (filename);
+ exit (FATAL);
+ }
+
+ {
+ int distance = indirect_info - the_file;
+ fwrite (the_file, 1, distance, output_stream);
+
+ /* Inhibit newlines. */
+ paragraph_is_open = 0;
+
+ write_tag_table_indirect ();
+ fclose (output_stream);
+ free (the_header);
+ free (the_file);
+ return;
+ }
+ }
+}
+
+/* Some menu hacking. This is used to remember menu references while
+ reading the input file. After the output file has been written, if
+ validation is on, then we use the contents of NODE_REFERENCES as a
+ list of nodes to validate. */
+char *
+reftype_type_string (type)
+ enum reftype type;
+{
+ switch (type)
+ {
+ case menu_reference:
+ return ("Menu");
+ case followed_reference:
+ return ("Followed-Reference");
+ default:
+ return ("Internal-bad-reference-type");
+ }
+}
+
+/* Remember this node name for later validation use. */
+#ifdef TRACK_SRCFILE
+remember_node_reference (node, line, src_line, type)
+#else
+remember_node_reference (node, line, type)
+#endif /* TRACK_SRCFILE */
+ char *node;
+ int line;
+#ifdef TRACK_SRCFILE
+ int src_line;
+#endif /* TRACK_SRCFILE */
+ enum reftype type;
+{
+ NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF));
+
+ temp->next = node_references;
+ temp->node = savestring (node);
+ temp->line_no = line;
+#ifdef TRACK_SRCFILE
+ temp->src_lineno = src_line;
+#endif /* TRACK_SRCFILE */
+ temp->section = current_section;
+ temp->type = type;
+ temp->containing_node = savestring (current_node);
+ temp->filename = node_filename;
+#ifdef TRACK_SRCFILE
+ temp->src_filename = node_src_filename;
+#endif /* TRACK_SRCFILE */
+
+ node_references = temp;
+}
+
+validate_other_references (ref_list)
+ register NODE_REF *ref_list;
+{
+ char *old_input_filename = input_filename;
+#ifdef TRACK_SRCFILE
+ char *old_src_filename = src_filename;
+#endif /* TRACK_SRCFILE */
+
+ while (ref_list != (NODE_REF *) NULL)
+ {
+ input_filename = ref_list->filename;
+#ifdef TRACK_SRCFILE
+ src_filename = ref_list->src_filename;
+#endif /* TRACK_SRCFILE */
+ validate (ref_list->node, ref_list->line_no,
+#ifdef TRACK_SRCFILE
+ ref_list->src_lineno,
+#endif /* TRACK_SRCFILE */
+ reftype_type_string (ref_list->type));
+ ref_list = ref_list->next;
+ }
+ input_filename = old_input_filename;
+#ifdef TRACK_SRCFILE
+ src_filename = old_src_filename;
+#endif /* TRACK_SRCFILE */
+}
+
+/* Find NODE in REF_LIST. */
+NODE_REF *
+find_node_reference (node, ref_list)
+ char *node;
+ register NODE_REF *ref_list;
+{
+ while (ref_list)
+ {
+ if (stricmp (node, ref_list->node) == 0)
+ break;
+ ref_list = ref_list->next;
+ }
+ return (ref_list);
+}
+
+free_node_references ()
+{
+ register NODE_REF *list, *temp;
+
+ list = node_references;
+
+ while (list)
+ {
+ temp = list;
+ free (list->node);
+ free (list->containing_node);
+ list = list->next;
+ free (temp);
+ }
+ node_references = (NODE_REF *) NULL;
+}
+
+ /* This function gets called at the start of every line while inside of
+ a menu. It checks to see if the line starts with "* ", and if so,
+ remembers the node reference that this menu refers to.
+ input_text_offset is at the \n just before the line start. */
+#define menu_starter "* "
+char *
+glean_node_from_menu (remember_reference)
+ int remember_reference;
+{
+ int i, orig_offset = input_text_offset;
+ char *nodename;
+
+ if (strncmp (&input_text[input_text_offset + 1],
+ menu_starter,
+ strlen (menu_starter)) != 0)
+ return ((char *)NULL);
+ else
+ input_text_offset += strlen (menu_starter) + 1;
+
+ get_until_in_line (":", &nodename);
+ if (curchar () == ':')
+ input_text_offset++;
+ canon_white (nodename);
+
+ if (curchar () == ':')
+ goto save_node;
+
+ free (nodename);
+ get_rest_of_line (&nodename);
+
+ /* Special hack: If the nodename follows the menu item name,
+ then we have to read the rest of the line in order to find
+ out what the nodename is. But we still have to read the
+ line later, in order to process any formatting commands that
+ might be present. So un-count the carriage return that has just
+ been counted. */
+ line_number--;
+#ifdef TRACK_SRCFILE
+ src_lineno--;
+#endif /* TRACK_SRCFILE */
+
+ canon_white (nodename);
+ for (i = 0; i < strlen (nodename); i++)
+ {
+ if (nodename[i] == '\t' ||
+ nodename[i] == '.' ||
+ nodename[i] == ',')
+ {
+ nodename[i] = '\0';
+ break;
+ }
+ }
+save_node:
+ input_text_offset = orig_offset;
+ normalize_node_name (nodename);
+ i = strlen (nodename);
+ if (i && nodename[i - 1] == ':')
+ nodename[i - 1] = '\0';
+
+ if (remember_reference)
+ {
+#ifdef TRACK_SRCFILE
+ remember_node_reference (nodename, line_number, src_lineno, menu_reference);
+#else
+ remember_node_reference (nodename, line_number, menu_reference);
+#endif /* TRACK_SRCFILE */
+ free (nodename);
+ return ((char *)NULL);
+ }
+ else
+ return (nodename);
+}
+
+cm_menu ()
+{
+ begin_insertion (menu);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Cross Reference Hacking */
+/* */
+/* **************************************************************** */
+
+char *
+get_xref_token ()
+{
+ char *string;
+
+ get_until_in_braces (",", &string);
+ if (curchar () == ',')
+ input_text_offset++;
+ fix_whitespace (string);
+ return (string);
+}
+
+int px_ref_flag = 0; /* Controls initial output string. */
+
+/* Make a cross reference. */
+cm_xref (arg)
+{
+ if (arg == START)
+ {
+ char *arg1, *arg2, *arg3, *arg4, *arg5;
+
+ arg1 = get_xref_token ();
+ arg2 = get_xref_token ();
+ arg3 = get_xref_token ();
+ arg4 = get_xref_token ();
+ arg5 = get_xref_token ();
+
+ add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
+
+ if (*arg5 || *arg4)
+ {
+ char *node_name;
+
+ if (!*arg2)
+ {
+ if (*arg3)
+ node_name = arg3;
+ else
+ node_name = arg1;
+ }
+ else
+ node_name = arg2;
+
+ execute_string ("%s: (%s)%s", node_name, arg4, arg1);
+ return;
+ }
+ else
+#ifdef TRACK_SRCFILE
+ remember_node_reference (arg1, line_number, src_lineno, followed_reference);
+#else
+ remember_node_reference (arg1, line_number, followed_reference);
+#endif /* TRACK_SRCFILE */
+
+ if (*arg3)
+ {
+ if (!*arg2)
+ execute_string ("%s: %s", arg3, arg1);
+ else
+ execute_string ("%s: %s", arg2, arg1);
+ return;
+ }
+
+ if (*arg2)
+ execute_string ("%s: %s", arg2, arg1);
+ else
+ execute_string ("%s::", arg1);
+ }
+ else
+ {
+
+ /* Check to make sure that the next non-whitespace character is either
+ a period or a comma. input_text_offset is pointing at the "}" which
+ ended the xref or pxref command. */
+ int temp = input_text_offset + 1;
+
+ if (output_paragraph[output_paragraph_offset - 2] == ':' &&
+ output_paragraph[output_paragraph_offset - 1] == ':')
+ return;
+ while (temp < size_of_input_text)
+ {
+ if (cr_or_whitespace (input_text[temp]))
+ temp++;
+ else
+ {
+ if (input_text[temp] == '.' ||
+ input_text[temp] == ',' ||
+ input_text[temp] == '\t')
+ return;
+ else
+ {
+ line_error ("Cross-reference must be terminated with a period or a comma");
+ return;
+ }
+ }
+ }
+ }
+}
+
+cm_pxref (arg)
+ int arg;
+{
+ if (arg == START)
+ {
+ px_ref_flag++;
+ cm_xref (arg);
+ px_ref_flag--;
+ }
+ else
+ add_char ('.');
+}
+
+cm_inforef (arg)
+ int arg;
+{
+ if (arg == START)
+ {
+ char *node, *pname, *file;
+
+ node = get_xref_token ();
+ pname = get_xref_token ();
+ file = get_xref_token ();
+
+ execute_string ("*note %s: (%s)%s", pname, file, node);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Insertion Command Stubs */
+/* */
+/* **************************************************************** */
+
+cm_quotation ()
+{
+ begin_insertion (quotation);
+}
+
+cm_example ()
+{
+ begin_insertion (example);
+}
+
+cm_smallexample ()
+{
+ begin_insertion (smallexample);
+}
+
+cm_lisp ()
+{
+ begin_insertion (lisp);
+}
+
+cm_smalllisp ()
+{
+ begin_insertion (smalllisp);
+}
+
+/* @cartouche/@end cartouche draws box with rounded corners in
+ TeX output. Right now, just a NOP insertion. */
+cm_cartouche ()
+{
+ begin_insertion (cartouche);
+}
+
+cm_format ()
+{
+ begin_insertion (format);
+}
+
+cm_display ()
+{
+ begin_insertion (display);
+}
+
+cm_itemize ()
+{
+ begin_insertion (itemize);
+}
+
+cm_enumerate ()
+{
+ do_enumeration (enumerate, "1");
+}
+
+/* Start an enumeration insertion of type TYPE. If the user supplied
+ no argument on the line, then use DEFAULT_STRING as the initial string. */
+do_enumeration (type, default_string)
+ int type;
+ char *default_string;
+{
+ get_until_in_line (".", &enumeration_arg);
+ canon_white (enumeration_arg);
+
+ if (!*enumeration_arg)
+ {
+ free (enumeration_arg);
+ enumeration_arg = savestring (default_string);
+ }
+
+ if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
+ {
+ warning ("%s requires a letter or a digit", insertion_type_pname (type));
+
+ switch (type)
+ {
+ case enumerate:
+ default_string = "1";
+ break;
+ }
+ enumeration_arg = savestring (default_string);
+ }
+ begin_insertion (type);
+}
+
+cm_table ()
+{
+ begin_insertion (table);
+}
+
+cm_ftable ()
+{
+ begin_insertion (ftable);
+}
+
+cm_vtable ()
+{
+ begin_insertion (vtable);
+}
+
+cm_group ()
+{
+ begin_insertion (group);
+}
+
+cm_ifinfo ()
+{
+ begin_insertion (ifinfo);
+}
+
+/* Begin an insertion where the lines are not filled or indented. */
+cm_flushleft ()
+{
+ begin_insertion (flushleft);
+}
+
+/* Begin an insertion where the lines are not filled, and each line is
+ forced to the right-hand side of the page. */
+cm_flushright ()
+{
+ begin_insertion (flushright);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Conditional Handling */
+/* */
+/* **************************************************************** */
+
+/* A structure which contains `defined' variables. */
+typedef struct _defines {
+ struct _defines *next;
+ char *name;
+ char *value;
+} DEFINE;
+
+/* The linked list of `set' defines. */
+DEFINE *defines = (DEFINE *)NULL;
+
+/* Add NAME to the list of `set' defines. */
+set (name, value)
+ char *name;
+ char *value;
+{
+ DEFINE *temp;
+
+ for (temp = defines; temp; temp = temp->next)
+ if (strcmp (name, temp->name) == 0)
+ {
+ free (temp->value);
+ temp->value = savestring (value);
+ return;
+ }
+
+ temp = (DEFINE *)xmalloc (sizeof (DEFINE));
+ temp->next = defines;
+ temp->name = savestring (name);
+ temp->value = savestring (value);
+ defines = temp;
+}
+
+/* Remove NAME from the list of `set' defines. */
+clear (name)
+ char *name;
+{
+ register DEFINE *temp, *last;
+
+ last = (DEFINE *)NULL;
+ temp = defines;
+
+ while (temp)
+ {
+ if (strcmp (temp->name, name) == 0)
+ {
+ if (last)
+ last->next = temp->next;
+ else
+ defines = temp->next;
+
+ free (temp->name);
+ free (temp->value);
+ free (temp);
+ break;
+ }
+ last = temp;
+ temp = temp->next;
+ }
+}
+
+/* Return the value of NAME. The return value is NULL if NAME is unset. */
+char *
+set_p (name)
+ char *name;
+{
+ register DEFINE *temp;
+
+ for (temp = defines; temp; temp = temp->next)
+ if (strcmp (temp->name, name) == 0)
+ return (temp->value);
+
+ return ((char *)NULL);
+}
+
+/* Conditionally parse based on the current command name. */
+command_name_condition ()
+{
+ char *discarder;
+
+ discarder = (char *)xmalloc (8 + strlen (command));
+
+ sprintf (discarder, "\n@end %s", command);
+ discard_until (discarder);
+ discard_until ("\n");
+
+ free (discarder);
+}
+
+/* Create a variable whose name appears as the first word on this line. */
+cm_set ()
+{
+ handle_variable (SET);
+}
+
+/* Remove a variable whose name appears as the first word on this line. */
+cm_clear ()
+{
+ handle_variable (CLEAR);
+}
+
+cm_ifset ()
+{
+ handle_variable (IFSET);
+}
+
+cm_ifclear ()
+{
+ handle_variable (IFCLEAR);
+}
+
+cm_value (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ if (arg == END)
+ {
+ char *name, *value;
+ name = (char *)&output_paragraph[start_pos];
+ output_paragraph[end_pos] = '\0';
+ name = savestring (name);
+ value = set_p (name);
+ output_paragraph_offset = start_pos;
+
+ if (value)
+ add_word_args ("%s", value);
+ else
+ add_word_args ("{No Value For \"%s\"}", name);
+
+ free (name);
+ }
+}
+
+/* Set, clear, or conditionalize based on ACTION. */
+handle_variable (action)
+ int action;
+{
+ char *name;
+
+ get_rest_of_line (&name);
+ backup_input_pointer ();
+ canon_white (name);
+ handle_variable_internal (action, name);
+ free (name);
+}
+
+handle_variable_internal (action, name)
+ int action;
+ char *name;
+{
+ char *value, *temp;
+ int delimiter;
+
+ /* Only the first word of NAME is a valid tag. */
+ temp = name;
+ delimiter = 0;
+ while (*temp && (delimiter || !whitespace (*temp)))
+ {
+ if (*temp == '"' || *temp == '\'')
+ {
+ if (*temp == delimiter)
+ delimiter = 0;
+ else
+ delimiter = *temp;
+ }
+ temp++;
+ }
+ *temp = '\0';
+
+ if (!*name)
+ line_error ("@%s requires a name", command);
+ else
+ {
+ switch (action)
+ {
+ case SET:
+ {
+ /* Allow a value to be saved along with a variable. The value is
+ the text following an `=' sign in NAME, if any is present. */
+ char *value;
+ int delimiter;
+
+ for (value = name; *value && *value != '='; value++);
+
+ if (*value)
+ *value++ = '\0';
+
+ if (*value == '"' || *value == '\'')
+ {
+ value++;
+ value[strlen (value) - 1] = '\0';
+ }
+
+ set (name, value);
+ }
+ break;
+
+ case CLEAR:
+ clear (name);
+ break;
+
+ case IFSET:
+ case IFCLEAR:
+ /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
+ read lines from the the file until we reach a matching
+ "@end CONDITION". This means that we only take note of
+ "@ifset/clear" and "@end" commands. */
+ {
+ char condition[8];
+ int condition_len;
+
+ if (action == IFSET)
+ strcpy (condition, "ifset");
+ else
+ strcpy (condition, "ifclear");
+
+ condition_len = strlen (condition);
+
+ if ((action == IFSET && !set_p (name)) ||
+ (action == IFCLEAR && set_p (name)))
+ {
+ int level = 0, done = 0;
+
+ while (!done)
+ {
+ char *freeable_line, *line;
+
+ get_rest_of_line (&freeable_line);
+
+ for (line = freeable_line; whitespace (*line); line++);
+
+ if (*line == COMMAND_PREFIX &&
+ (strncmp (line + 1, condition, condition_len) == 0))
+ level++;
+ else if (strncmp (line, "@end", 4) == 0)
+ {
+ char *cname = line + 4;
+ char *temp;
+
+ while (*cname && whitespace (*cname))
+ cname++;
+ temp = cname;
+
+ while (*temp && !whitespace (*temp))
+ temp++;
+ *temp = '\0';
+
+ if (strcmp (cname, condition) == 0)
+ {
+ if (!level)
+ {
+ done = 1;
+ }
+ else
+ level--;
+ }
+ }
+ free (freeable_line);
+ }
+ break;
+ }
+ else
+ {
+ if (action == IFSET)
+ begin_insertion (ifset);
+ else
+ begin_insertion (ifclear);
+ }
+ }
+ break;
+ }
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* @itemx, @item */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means a string is in execution, as opposed to a file. */
+int executing_string = 0;
+
+/* Execute the string produced by formatting the ARGs with FORMAT. This
+ is like submitting a new file with @include. */
+execute_string (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ static char temp_string[4000];
+ sprintf (temp_string, format, arg1, arg2, arg3, arg4, arg5);
+ strcat (temp_string, "@bye\n");
+ pushfile ();
+ input_text_offset = 0;
+ input_text = temp_string;
+ input_filename = savestring (input_filename);
+#ifdef TRACK_SRCFILE
+ src_filename = savestring (src_filename);
+#endif /* TRACK_SRCFILE */
+ size_of_input_text = strlen (temp_string);
+
+ executing_string++;
+ reader_loop ();
+
+ popfile ();
+ executing_string--;
+
+ free_and_clear (&command);
+ command = savestring ("not bye");
+}
+
+int itemx_flag = 0;
+
+cm_itemx ()
+{
+ itemx_flag++;
+ cm_item ();
+ itemx_flag--;
+}
+
+cm_item ()
+{
+ char *rest_of_line, *item_func;
+
+ /* Can only hack "@item" while inside of an insertion. */
+ if (insertion_level)
+ {
+ INSERTION_ELT *stack = insertion_stack;
+ int original_input_text_offset;
+
+ skip_whitespace ();
+ original_input_text_offset = input_text_offset;
+
+ get_rest_of_line (&rest_of_line);
+ canon_white (rest_of_line);
+ item_func = current_item_function ();
+
+ /* Okay, do the right thing depending on which insertion function
+ is active. */
+
+ switch_top:
+ switch (stack->insertion)
+ {
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ case cartouche:
+ stack = stack->next;
+ if (!stack)
+ goto no_insertion;
+ else
+ goto switch_top;
+ break;
+
+ case menu:
+ case quotation:
+ case example:
+ case smallexample:
+ case lisp:
+ case format:
+ case display:
+ case group:
+ line_error ("The `@%s' command is meaningless within a `@%s' block",
+ command,
+ insertion_type_pname (current_insertion_type ()));
+ break;
+
+ case itemize:
+ case enumerate:
+ if (itemx_flag)
+ {
+ line_error ("@itemx is not meaningful inside of a `%s' block",
+ insertion_type_pname (current_insertion_type ()));
+ }
+ else
+ {
+ start_paragraph ();
+ kill_self_indent (-1);
+ filling_enabled = indented_fill = 1;
+
+ if (current_insertion_type () == itemize)
+ {
+ indent (output_column = current_indent - 2);
+
+ /* I need some way to determine whether this command
+ takes braces or not. I believe the user can type
+ either "@bullet" or "@bullet{}". Of course, they
+ can also type "o" or "#" or whatever else they want. */
+ if (item_func && *item_func)
+ {
+ if (*item_func == '@')
+ if (item_func[strlen (item_func) - 1] != '}')
+ execute_string ("%s{}", item_func);
+ else
+ execute_string ("%s", item_func);
+ else
+ execute_string ("%s", item_func);
+ }
+ insert (' ');
+ output_column++;
+ }
+ else
+ enumerate_item ();
+
+ /* Special hack. This makes close paragraph ignore you until
+ the start_paragraph () function has been called. */
+ must_start_paragraph = 1;
+
+ /* Ultra special hack. It appears that some people incorrectly
+ place text directly after the @item, instead of on a new line
+ by itself. This happens to work in TeX, so I make it work
+ here. */
+ if (*rest_of_line)
+ {
+ line_number--;
+ input_text_offset = original_input_text_offset;
+ }
+ }
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ {
+ /* Get rid of extra characters. */
+ kill_self_indent (-1);
+
+ /* close_paragraph () almost does what we want. The problem
+ is when paragraph_is_open, and last_char_was_newline, and
+ the last newline has been turned into a space, because
+ filling_enabled. I handle it here. */
+ if (last_char_was_newline && filling_enabled && paragraph_is_open)
+ insert ('\n');
+ close_paragraph ();
+
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ /* Indent on a new line, but back up one indentation level. */
+ {
+ int t;
+
+ t = inhibit_paragraph_indentation;
+ inhibit_paragraph_indentation = 1;
+ /* At this point, inserting any non-whitespace character will
+ force the existing indentation to be output. */
+ add_char ('i');
+ inhibit_paragraph_indentation = t;
+ }
+#else /* !INDENT_PARAGRAPHS_IN_TABLE */
+ add_char ('i');
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ output_paragraph_offset--;
+ kill_self_indent (default_indentation_increment + 1);
+
+ /* Add item's argument to the line. */
+ filling_enabled = 0;
+ if (!item_func && !(*item_func))
+ execute_string ("%s", rest_of_line);
+ else
+ execute_string ("%s{%s}", item_func, rest_of_line);
+
+ if (current_insertion_type () == ftable)
+ execute_string ("@findex %s\n", rest_of_line);
+
+ if (current_insertion_type () == vtable)
+ execute_string ("@vindex %s\n", rest_of_line);
+
+ /* Start a new line, and let start_paragraph ()
+ do the indenting of it for you. */
+ close_single_paragraph ();
+ indented_fill = filling_enabled = 1;
+ }
+ }
+ free (rest_of_line);
+ }
+ else
+ {
+ no_insertion:
+ line_error ("@%s found outside of an insertion block", command);
+ }
+}
+
+
+/* **************************************************************** */
+/* */
+/* Defun and Friends */
+/* */
+/* **************************************************************** */
+
+#define DEFUN_SELF_DELIMITING(c) \
+ (((c) == '(') \
+ || ((c) == ')') \
+ || ((c) == '[') \
+ || ((c) == ']'))
+
+struct token_accumulator
+{
+ unsigned int length;
+ unsigned int index;
+ char **tokens;
+};
+
+void
+initialize_token_accumulator (accumulator)
+ struct token_accumulator *accumulator;
+{
+ (accumulator->length) = 0;
+ (accumulator->index) = 0;
+ (accumulator->tokens) = NULL;
+}
+
+void
+accumulate_token (accumulator, token)
+ struct token_accumulator *accumulator;
+ char *token;
+{
+ if ((accumulator->index) >= (accumulator->length))
+ {
+ (accumulator->length) += 10;
+ (accumulator->tokens) = (char **) xrealloc
+ (accumulator->tokens, (accumulator->length * sizeof (char *)));
+ }
+ accumulator->tokens[accumulator->index] = token;
+ accumulator->index += 1;
+}
+
+char *
+copy_substring (start, end)
+ char *start;
+ char *end;
+{
+ char *result, *scan, *scan_result;
+
+ result = (char *) xmalloc ((end - start) + 1);
+ scan_result = result;
+ scan = start;
+
+ while (scan < end)
+ *scan_result++ = *scan++;
+
+ *scan_result = '\0';
+ return (result);
+}
+
+/* Given `string' pointing at an open brace, skip forward and return a
+ pointer to just past the matching close brace. */
+int
+scan_group_in_string (string_pointer)
+ char **string_pointer;
+{
+ register int c;
+ register char *scan_string;
+ register unsigned int level = 1;
+
+ scan_string = (*string_pointer) + 1;
+
+ while (1)
+ {
+ if (level == 0)
+ {
+ (*string_pointer) = scan_string;
+ return (1);
+ }
+ c = (*scan_string++);
+ if (c == '\0')
+ {
+ /* Tweak line_number to compensate for fact that
+ we gobbled the whole line before coming here. */
+ line_number -= 1;
+ line_error ("Missing `}' in @def arg");
+ line_number += 1;
+ (*string_pointer) = (scan_string - 1);
+ return (0);
+ }
+ if (c == '{')
+ level += 1;
+ if (c == '}')
+ level -= 1;
+ }
+}
+
+/* Return a list of tokens from the contents of `string'.
+ Commands and brace-delimited groups count as single tokens.
+ Contiguous whitespace characters are converted to a token
+ consisting of a single space. */
+char **
+args_from_string (string)
+ char *string;
+{
+ struct token_accumulator accumulator;
+ register char *scan_string = string;
+ char *token_start, *token_end;
+
+ initialize_token_accumulator (&accumulator);
+
+ while ((*scan_string) != '\0')
+ {
+ /* Replace arbitrary whitespace by a single space. */
+ if (whitespace (*scan_string))
+ {
+ scan_string += 1;
+ while (whitespace (*scan_string))
+ scan_string += 1;
+ accumulate_token ((&accumulator), (savestring (" ")));
+ continue;
+ }
+
+ /* Commands count as single tokens. */
+ if ((*scan_string) == COMMAND_PREFIX)
+ {
+ token_start = scan_string;
+ scan_string += 1;
+ if (self_delimiting (*scan_string))
+ scan_string += 1;
+ else
+ {
+ register int c;
+ while (1)
+ {
+ c = *scan_string++;
+
+ if ((c == '\0') || (c == '{') || (whitespace (c)))
+ {
+ scan_string -= 1;
+ break;
+ }
+ }
+
+ if (*scan_string == '{')
+ {
+ char *s = scan_string;
+ (void) scan_group_in_string (&s);
+ scan_string = s;
+ }
+ }
+ token_end = scan_string;
+ }
+
+ /* Parentheses and brackets are self-delimiting. */
+ else if (DEFUN_SELF_DELIMITING (*scan_string))
+ {
+ token_start = scan_string;
+ scan_string += 1;
+ token_end = scan_string;
+ }
+
+ /* Open brace introduces a group that is a single token. */
+ else if (*scan_string == '{')
+ {
+ char *s = scan_string;
+ int balanced = scan_group_in_string (&s);
+
+ token_start = scan_string + 1;
+ scan_string = s;
+ token_end = balanced ? (scan_string - 1) : scan_string;
+ }
+
+ /* Otherwise a token is delimited by whitespace, parentheses,
+ brackets, or braces. A token is also ended by a command. */
+ else
+ {
+ token_start = scan_string;
+
+ while (1)
+ {
+ register int c;
+
+ c = *scan_string++;
+
+ if (!c ||
+ (whitespace (c) || DEFUN_SELF_DELIMITING (c) ||
+ c == '{' || c == '}'))
+ {
+ scan_string--;
+ break;
+ }
+
+ /* If we encounter a command imbedded within a token,
+ then end the token. */
+ if (c == COMMAND_PREFIX)
+ {
+ scan_string--;
+ break;
+ }
+ }
+ token_end = scan_string;
+ }
+
+ accumulate_token
+ (&accumulator, copy_substring (token_start, token_end));
+ }
+ accumulate_token (&accumulator, NULL);
+ return (accumulator.tokens);
+}
+
+void
+process_defun_args (defun_args, auto_var_p)
+ char **defun_args;
+ int auto_var_p;
+{
+ int pending_space = 0;
+
+ while (1)
+ {
+ char *defun_arg = *defun_args++;
+
+ if (defun_arg == NULL)
+ break;
+
+ if (defun_arg[0] == ' ')
+ {
+ pending_space = 1;
+ continue;
+ }
+
+ if (pending_space)
+ {
+ add_char (' ');
+ pending_space = 0;
+ }
+
+ if (DEFUN_SELF_DELIMITING (defun_arg[0]))
+ add_char (defun_arg[0]);
+ else if (defun_arg[0] == '&')
+ add_word (defun_arg);
+ else if (defun_arg[0] == COMMAND_PREFIX)
+ execute_string ("%s", defun_arg);
+ else if (auto_var_p)
+ execute_string ("@var{%s}", defun_arg);
+ else
+ add_word (defun_arg);
+ }
+}
+
+char *
+next_nonwhite_defun_arg (arg_pointer)
+ char ***arg_pointer;
+{
+ char **scan = (*arg_pointer);
+ char *arg = (*scan++);
+
+ if ((arg != 0) && (*arg == ' '))
+ arg = *scan++;
+
+ if (arg == 0)
+ scan -= 1;
+
+ *arg_pointer = scan;
+
+ return ((arg == 0) ? "" : arg);
+}
+
+/* Make the defun type insertion.
+ TYPE says which insertion this is.
+ X_P says not to start a new insertion if non-zero. */
+void
+defun_internal (type, x_p)
+ enum insertion_type type;
+ int x_p;
+{
+ enum insertion_type base_type;
+ char **defun_args, **scan_args;
+ char *category, *defined_name, *type_name, *type_name2;
+
+ {
+ char *line;
+ get_rest_of_line (&line);
+ defun_args = (args_from_string (line));
+ free (line);
+ }
+
+ scan_args = defun_args;
+
+ switch (type)
+ {
+ case defun:
+ category = "Function";
+ base_type = deffn;
+ break;
+ case defmac:
+ category = "Macro";
+ base_type = deffn;
+ break;
+ case defspec:
+ category = "Special Form";
+ base_type = deffn;
+ break;
+ case defvar:
+ category = "Variable";
+ base_type = defvr;
+ break;
+ case defopt:
+ category = "User Option";
+ base_type = defvr;
+ break;
+ case deftypefun:
+ category = "Function";
+ base_type = deftypefn;
+ break;
+ case deftypevar:
+ category = "Variable";
+ base_type = deftypevr;
+ break;
+ case defivar:
+ category = "Instance Variable";
+ base_type = defcv;
+ break;
+ case defmethod:
+ category = "Method";
+ base_type = defop;
+ break;
+ case deftypemethod:
+ category = "Method";
+ base_type = deftypemethod;
+ break;
+ default:
+ category = next_nonwhite_defun_arg (&scan_args);
+ base_type = type;
+ break;
+ }
+
+ if ((base_type == deftypefn)
+ || (base_type == deftypevr)
+ || (base_type == defcv)
+ || (base_type == defop)
+ || (base_type == deftypemethod))
+ type_name = next_nonwhite_defun_arg (&scan_args);
+
+ if (base_type == deftypemethod)
+ type_name2 = next_nonwhite_defun_arg (&scan_args);
+
+ defined_name = next_nonwhite_defun_arg (&scan_args);
+
+ /* This hack exists solely for the purposes of formatting the texinfo
+ manual. I couldn't think of a better way. The token might be
+ a simple @@ followed immediately by more text. If this is the case,
+ then the next defun arg is part of this one, and we should concatenate
+ them. */
+ if (*scan_args && **scan_args && !whitespace (**scan_args) &&
+ (strcmp (defined_name, "@@") == 0))
+ {
+ char *tem = (char *)xmalloc (3 + strlen (scan_args[0]));
+
+ sprintf (tem, "@@%s", scan_args[0]);
+
+ free (scan_args[0]);
+ scan_args[0] = tem;
+ scan_args++;
+ defined_name = tem;
+ }
+
+ if (!x_p)
+ begin_insertion (type);
+
+ /* Write the definition header line.
+ This should start at the normal indentation. */
+ current_indent -= default_indentation_increment;
+ start_paragraph ();
+
+ switch (base_type)
+ {
+ case deffn:
+ case defvr:
+ case deftp:
+ execute_string (" -- %s: %s", category, defined_name);
+ break;
+ case deftypefn:
+ case deftypevr:
+ execute_string (" -- %s: %s %s", category, type_name, defined_name);
+ break;
+ case defcv:
+ execute_string (" -- %s of %s: %s", category, type_name, defined_name);
+ break;
+ case defop:
+ execute_string (" -- %s on %s: %s", category, type_name, defined_name);
+ break;
+ case deftypemethod:
+ execute_string (" -- %s on %s: %s %s", category, type_name, type_name2,
+ defined_name);
+ break;
+ }
+ current_indent += default_indentation_increment;
+
+ /* Now process the function arguments, if any.
+ If these carry onto the next line, they should be indented by two
+ increments to distinguish them from the body of the definition,
+ which is indented by one increment. */
+ current_indent += default_indentation_increment;
+
+ switch (base_type)
+ {
+ case deffn:
+ case defop:
+ process_defun_args (scan_args, 1);
+ break;
+ case deftp:
+ case deftypefn:
+ case deftypemethod:
+ process_defun_args (scan_args, 0);
+ break;
+ }
+ current_indent -= default_indentation_increment;
+ close_single_paragraph ();
+
+ /* Make an entry in the appropriate index. */
+ switch (base_type)
+ {
+ case deffn:
+ case deftypefn:
+ execute_string ("@findex %s\n", defined_name);
+ break;
+ case defvr:
+ case deftypevr:
+ case defcv:
+ execute_string ("@vindex %s\n", defined_name);
+ break;
+ case defop:
+ case deftypemethod:
+ execute_string ("@findex %s on %s\n", defined_name, type_name);
+ break;
+ case deftp:
+ execute_string ("@tindex %s\n", defined_name);
+ break;
+ }
+
+ /* Deallocate the token list. */
+ scan_args = defun_args;
+ while (1)
+ {
+ char * arg = (*scan_args++);
+ if (arg == NULL)
+ break;
+ free (arg);
+ }
+ free (defun_args);
+}
+
+/* Add an entry for a function, macro, special form, variable, or option.
+ If the name of the calling command ends in `x', then this is an extra
+ entry included in the body of an insertion of the same type. */
+cm_defun ()
+{
+ int x_p;
+ enum insertion_type type;
+ char *temp = savestring (command);
+
+ x_p = (command[strlen (command) - 1] == 'x');
+
+ if (x_p)
+ temp[strlen (temp) - 1] = '\0';
+
+ type = find_type_from_name (temp);
+ free (temp);
+
+ /* If we are adding to an already existing insertion, then make sure
+ that we are already in an insertion of type TYPE. */
+ if (x_p &&
+ (!insertion_level || insertion_stack->insertion != type))
+ {
+ line_error ("Must be in a `%s' insertion in order to use `%s'x",
+ command, command);
+ discard_until ("\n");
+ return;
+ }
+
+ defun_internal (type, x_p);
+}
+
+/* End existing insertion block. */
+cm_end ()
+{
+ char *temp;
+ enum insertion_type type;
+
+ if (!insertion_level)
+ {
+ line_error ("Unmatched `@%s'", command);
+ return;
+ }
+
+ get_rest_of_line (&temp);
+ canon_white (temp);
+
+ if (strlen (temp) == 0)
+ line_error ("`@%s' needs something after it", command);
+
+ type = find_type_from_name (temp);
+
+ if (type == bad_type)
+ {
+ line_error ("Bad argument to `%s', `%s', using `%s'",
+ command, temp, insertion_type_pname (current_insertion_type ()));
+ }
+ end_insertion (type);
+ free (temp);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Other Random Commands */
+/* */
+/* **************************************************************** */
+
+/* This says to inhibit the indentation of the next paragraph, but
+ not of following paragraphs. */
+cm_noindent ()
+{
+ if (!inhibit_paragraph_indentation)
+ inhibit_paragraph_indentation = -1;
+}
+
+/* I don't know exactly what to do with this. Should I allow
+ someone to switch filenames in the middle of output? Since the
+ file could be partially written, this doesn't seem to make sense.
+ Another option: ignore it, since they don't *really* want to
+ switch files. Finally, complain, or at least warn. */
+cm_setfilename ()
+{
+ char *filename;
+ get_rest_of_line (&filename);
+ /* warning ("`@%s %s' encountered and ignored", command, filename); */
+ free (filename);
+}
+
+cm_ignore_line ()
+{
+ discard_until ("\n");
+}
+
+/* @br can be immediately followed by `{}', so we have to read those here.
+ It should simply close the paragraph. */
+cm_br ()
+{
+ if (looking_at ("{}"))
+ input_text_offset += 2;
+
+ if (curchar () == '\n')
+ {
+ input_text_offset++;
+ line_number++;
+ }
+
+ close_paragraph ();
+}
+
+ /* Insert the number of blank lines passed as argument. */
+cm_sp ()
+{
+ int lines;
+ char *line;
+
+ get_rest_of_line (&line);
+
+ sscanf (line, "%d", &lines);
+ while (lines--)
+ add_char ('\n');
+ free (line);
+}
+
+/* Start a new line with just this text on it.
+ Then center the line of text.
+ This always ends the current paragraph. */
+cm_center ()
+{
+ register int i, start, length;
+ int fudge_factor = 1;
+ unsigned char *line;
+
+ close_paragraph ();
+ filling_enabled = indented_fill = 0;
+ cm_noindent ();
+ start = output_paragraph_offset;
+ inhibit_output_flushing ();
+ get_rest_of_line ((char **)&line);
+ execute_string ((char *)line);
+ free (line);
+ uninhibit_output_flushing ();
+
+ i = output_paragraph_offset - 1;
+ while (i > (start - 1) && output_paragraph[i] == '\n')
+ i--;
+
+ output_paragraph_offset = ++i;
+ length = output_paragraph_offset - start;
+
+ if (length < (fill_column - fudge_factor))
+ {
+ line = (unsigned char *)xmalloc (1 + length);
+ bcopy (output_paragraph + start, line, length);
+
+ i = (fill_column - fudge_factor - length) / 2;
+ output_paragraph_offset = start;
+
+ while (i--)
+ insert (' ');
+
+ for (i = 0; i < length; i++)
+ insert (line[i]);
+
+ free (line);
+ }
+
+ insert ('\n');
+ close_paragraph ();
+ filling_enabled = 1;
+}
+
+/* Show what an expression returns. */
+cm_result (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("=>");
+}
+
+/* What an expression expands to. */
+cm_expansion (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("==>");
+}
+
+/* Indicates two expressions are equivalent. */
+cm_equiv (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("==");
+}
+
+/* What an expression may print. */
+cm_print (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("-|");
+}
+
+/* An error signaled. */
+cm_error (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("error-->");
+}
+
+/* The location of point in an example of a buffer. */
+cm_point (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("-!-");
+}
+
+/* Start a new line with just this text on it.
+ The text is outdented one level if possible. */
+cm_exdent ()
+{
+ char *line;
+ int i = current_indent;
+
+ if (current_indent)
+ current_indent -= default_indentation_increment;
+
+ get_rest_of_line (&line);
+ close_single_paragraph ();
+ execute_string (line);
+ current_indent = i;
+ free (line);
+ close_single_paragraph ();
+}
+
+cm_include ()
+{
+ cm_infoinclude ();
+}
+
+/* Remember this file, and move onto the next. */
+cm_infoinclude ()
+{
+ char *filename;
+
+ close_paragraph ();
+ get_rest_of_line (&filename);
+ pushfile ();
+
+ /* In verbose mode we print info about including another file. */
+ if (verbose_mode)
+ {
+ register int i = 0;
+ register FSTACK *stack = filestack;
+
+ for (i = 0, stack = filestack; stack; stack = stack->next, i++);
+
+ i *= 2;
+
+ printf ("%*s", i, "");
+ printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
+ fflush (stdout);
+ }
+
+ if (!find_and_load (filename))
+ {
+ extern char *sys_errlist[];
+ extern int errno, sys_nerr;
+ popfile ();
+
+ /* Cannot "@include foo", in line 5 of "/wh/bar". */
+ line_error ("`%c%s %s': %s", COMMAND_PREFIX, command, filename,
+ ((errno < sys_nerr) ?
+ sys_errlist[errno] : "Unknown file system error"));
+ }
+ free (filename);
+}
+
+/* The other side of a malformed expression. */
+misplaced_brace ()
+{
+#ifdef ALLOW_JUNK
+ warning ("Misplaced `}'");
+ add_word ("}");
+#else
+ line_error ("Misplaced `}'");
+#endif
+}
+
+/* Don't let the filling algorithm insert extra whitespace here. */
+cm_force_abbreviated_whitespace ()
+{
+}
+
+/* Do not let this character signify the end of a sentence, though
+ if it was seen without the command prefix it normally would. We
+ do this by turning on the 8th bit of the character. */
+cm_ignore_sentence_ender ()
+{
+ add_char (META ((*command)));
+}
+
+/* Signals end of processing. Easy to make this happen. */
+cm_bye ()
+{
+ input_text_offset = size_of_input_text;
+}
+
+cm_asis ()
+{
+}
+
+cm_math ()
+{
+}
+
+#ifdef TRACK_SRCFILE
+cm_srcfilename ()
+{
+ get_rest_of_line (&src_filename);
+}
+
+cm_srclineno ()
+{
+ char *temp;
+ get_rest_of_line (&temp);
+ sscanf(temp, "%d", &src_lineno);
+ free (temp);
+}
+#endif /* TRACK_SRCFILE */
+
+/* **************************************************************** */
+/* */
+/* Indexing Stuff */
+/* */
+/* **************************************************************** */
+
+
+/* An index element... */
+typedef struct index_elt
+{
+ struct index_elt *next;
+ char *entry; /* The index entry itself. */
+ char *node; /* The node from whence it came. */
+ int code; /* Non-zero means add `@code{...}' when
+ printing this element. */
+ int defining_line; /* Line number where this entry was written. */
+} INDEX_ELT;
+
+/* A list of short-names for each index, and the index to that index in our
+ index array, the_indices. In addition, for each index, it is remembered
+ whether that index is a code index or not. Code indices have @code{}
+ inserted around the first word when they are printed with printindex. */
+typedef struct
+{
+ char *name;
+ int index;
+ int code;
+} INDEX_ALIST;
+
+INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
+
+/* An array of pointers. Each one is for a different index. The
+ "synindex" command changes which array slot is pointed to by a
+ given "index". */
+INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
+
+/* The number of defined indices. */
+int defined_indices = 0;
+
+/* We predefine these. */
+#define program_index 0
+#define function_index 1
+#define concept_index 2
+#define variable_index 3
+#define datatype_index 4
+#define key_index 5
+
+init_indices ()
+{
+ int i;
+
+ /* Create the default data structures. */
+
+ /* Initialize data space. */
+ if (!the_indices)
+ {
+ the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
+ sizeof (INDEX_ELT *));
+ the_indices[defined_indices] = (INDEX_ELT *) NULL;
+
+ name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
+ sizeof (INDEX_ALIST *));
+ name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
+ }
+
+ /* If there were existing indices, get rid of them now. */
+ for (i = 0; i < defined_indices; i++)
+ undefindex (name_index_alist[i]->name);
+
+ /* Add the default indices. */
+ defindex ("pg", 0);
+ defindex ("fn", 1); /* "fn" is a code index. */
+ defindex ("cp", 0);
+ defindex ("vr", 0);
+ defindex ("tp", 0);
+ defindex ("ky", 0);
+
+}
+
+/* Find which element in the known list of indices has this name.
+ Returns -1 if NAME isn't found. */
+int
+find_index_offset (name)
+ char *name;
+{
+ register int i;
+ for (i = 0; i < defined_indices; i++)
+ if (name_index_alist[i] &&
+ stricmp (name, name_index_alist[i]->name) == 0)
+ return (name_index_alist[i]->index);
+ return (-1);
+}
+
+/* Return a pointer to the entry of (name . index) for this name.
+ Return NULL if the index doesn't exist. */
+INDEX_ALIST *
+find_index (name)
+ char *name;
+{
+ int offset = find_index_offset (name);
+ if (offset > -1)
+ return (name_index_alist[offset]);
+ else
+ return ((INDEX_ALIST *) NULL);
+}
+
+/* Given an index name, return the offset in the_indices of this index,
+ or -1 if there is no such index. */
+translate_index (name)
+ char *name;
+{
+ INDEX_ALIST *which = find_index (name);
+
+ if (which)
+ return (which->index);
+ else
+ return (-1);
+}
+
+/* Return the index list which belongs to NAME. */
+INDEX_ELT *
+index_list (name)
+ char *name;
+{
+ int which = translate_index (name);
+ if (which < 0)
+ return ((INDEX_ELT *) - 1);
+ else
+ return (the_indices[which]);
+}
+
+/* Please release me, let me go... */
+free_index (index)
+ INDEX_ELT *index;
+{
+ INDEX_ELT *temp;
+
+ while ((temp = index) != (INDEX_ELT *) NULL)
+ {
+ free (temp->entry);
+ free (temp->node);
+ index = index->next;
+ free (temp);
+ }
+}
+
+/* Flush an index by name. */
+undefindex (name)
+ char *name;
+{
+ int i;
+ int which = find_index_offset (name);
+
+ if (which < 0)
+ return (which);
+
+ i = name_index_alist[which]->index;
+
+
+ free_index (the_indices[i]);
+ the_indices[i] = (INDEX_ELT *) NULL;
+
+ free (name_index_alist[which]->name);
+ free (name_index_alist[which]);
+ name_index_alist[which] = (INDEX_ALIST *) NULL;
+}
+
+/* Define an index known as NAME. We assign the slot number.
+ CODE if non-zero says to make this a code index. */
+defindex (name, code)
+ char *name;
+ int code;
+{
+ register int i, slot;
+
+ /* If it already exists, flush it. */
+ undefindex (name);
+
+ /* Try to find an empty slot. */
+ slot = -1;
+ for (i = 0; i < defined_indices; i++)
+ if (!name_index_alist[i])
+ {
+ slot = i;
+ break;
+ }
+
+ if (slot < 0)
+ {
+ /* No such luck. Make space for another index. */
+ slot = defined_indices;
+ defined_indices++;
+
+ name_index_alist = (INDEX_ALIST **)
+ xrealloc ((char *)name_index_alist,
+ (1 + defined_indices) * sizeof (INDEX_ALIST *));
+ the_indices = (INDEX_ELT **)
+ xrealloc ((char *)the_indices,
+ (1 + defined_indices) * sizeof (INDEX_ELT *));
+ }
+
+ /* We have a slot. Start assigning. */
+ name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
+ name_index_alist[slot]->name = savestring (name);
+ name_index_alist[slot]->index = slot;
+ name_index_alist[slot]->code = code;
+
+ the_indices[slot] = (INDEX_ELT *) NULL;
+}
+
+/* Add the arguments to the current index command to the index NAME. */
+index_add_arg (name)
+ char *name;
+{
+ int which;
+ char *index_entry;
+ INDEX_ALIST *tem;
+
+ tem = find_index (name);
+
+ which = tem ? tem->index : -1;
+
+ get_rest_of_line (&index_entry);
+ ignore_blank_line ();
+
+ if (which < 0)
+ {
+ line_error ("Unknown index reference `%s'", name);
+ free (index_entry);
+ }
+ else
+ {
+ INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
+ new->next = the_indices[which];
+ new->entry = index_entry;
+ new->node = current_node;
+ new->code = tem->code;
+ new->defining_line = line_number - 1;
+ the_indices[which] = new;
+ }
+}
+
+#define INDEX_COMMAND_SUFFIX "index"
+
+/* The function which user defined index commands call. */
+gen_index ()
+{
+ char *name = savestring (command);
+ if (strlen (name) >= strlen ("index"))
+ name[strlen (name) - strlen ("index")] = '\0';
+ index_add_arg (name);
+ free (name);
+}
+
+/* Define a new index command. Arg is name of index. */
+cm_defindex ()
+{
+ gen_defindex (0);
+}
+
+cm_defcodeindex ()
+{
+ gen_defindex (1);
+}
+
+gen_defindex (code)
+ int code;
+{
+ char *name;
+ get_rest_of_line (&name);
+
+ if (find_index (name))
+ {
+ line_error ("Index `%s' already exists", name);
+ free (name);
+ return;
+ }
+ else
+ {
+ char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
+ sprintf (temp, "%sindex", name);
+ define_user_command (temp, gen_index, 0);
+ defindex (name, code);
+ free (name);
+ }
+}
+
+/* Append LIST2 to LIST1. Return the head of the list. */
+INDEX_ELT *
+index_append (head, tail)
+ INDEX_ELT *head, *tail;
+{
+ register INDEX_ELT *t_head = head;
+
+ if (!t_head)
+ return (tail);
+
+ while (t_head->next)
+ t_head = t_head->next;
+ t_head->next = tail;
+ return (head);
+}
+
+/* Expects 2 args, on the same line. Both are index abbreviations.
+ Make the first one be a synonym for the second one, i.e. make the
+ first one have the same index as the second one. */
+cm_synindex ()
+{
+ int redirector, redirectee;
+ char *temp;
+
+ skip_whitespace ();
+ get_until_in_line (" ", &temp);
+ redirectee = find_index_offset (temp);
+ skip_whitespace ();
+ free_and_clear (&temp);
+ get_until_in_line (" ", &temp);
+ redirector = find_index_offset (temp);
+ free (temp);
+ if (redirector < 0 || redirectee < 0)
+ {
+ line_error ("Unknown index reference");
+ }
+ else
+ {
+ /* I think that we should let the user make indices synonymous to
+ each other without any lossage of info. This means that one can
+ say @synindex cp dt anywhere in the file, and things that used to
+ be in cp will go into dt. */
+ INDEX_ELT *i1 = the_indices[redirectee], *i2 = the_indices[redirector];
+
+ if (i1 || i2)
+ {
+ if (i1)
+ the_indices[redirectee] = index_append (i1, i2);
+ else
+ the_indices[redirectee] = index_append (i2, i1);
+ }
+
+ name_index_alist[redirectee]->index =
+ name_index_alist[redirector]->index;
+ }
+}
+
+cm_pindex () /* Pinhead index. */
+{
+ index_add_arg ("pg");
+}
+
+cm_vindex () /* Variable index. */
+{
+ index_add_arg ("vr");
+}
+
+cm_kindex () /* Key index. */
+{
+ index_add_arg ("ky");
+}
+
+cm_cindex () /* Concept index. */
+{
+ index_add_arg ("cp");
+}
+
+cm_findex () /* Function index. */
+{
+ index_add_arg ("fn");
+}
+
+cm_tindex () /* Data Type index. */
+{
+ index_add_arg ("tp");
+}
+
+/* Sorting the index. */
+/* partain: added 2nd test if entries are the same */
+index_element_compare (element1, element2)
+ INDEX_ELT **element1, **element2;
+{
+/* old
+ return (strcmp ((*element1)->entry, (*element2)->entry));
+*/
+
+ int result;
+ /* This needs to ignore leading non-text characters. */
+ result = strcmp ((*element1)->entry, (*element2)->entry);
+
+ if (result != 0)
+ return(result);
+ else
+ return (strcmp ((*element1)->node, (*element2)->node));
+}
+
+/* Sort the index passed in INDEX, returning an array of
+ pointers to elements. The array is terminated with a NULL
+ pointer. We call qsort because it's supposed to be fast.
+ I think this looks bad. */
+INDEX_ELT **
+sort_index (index)
+ INDEX_ELT *index;
+{
+ INDEX_ELT *temp = index;
+ INDEX_ELT **array;
+ int count = 0;
+
+ while (temp != (INDEX_ELT *) NULL)
+ {
+ count++;
+ temp = temp->next;
+ }
+
+ /* We have the length. Make an array. */
+
+ array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
+ count = 0;
+ temp = index;
+
+ while (temp != (INDEX_ELT *) NULL)
+ {
+ array[count++] = temp;
+ temp = temp->next;
+ }
+ array[count] = (INDEX_ELT *) NULL; /* terminate the array. */
+
+ /* Sort the array. */
+ qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
+
+ return (array);
+}
+
+/* Non-zero means that we are in the middle of printing an index. */
+int printing_index = 0;
+
+/* Takes one arg, a short name of an index to print.
+ Outputs a menu of the sorted elements of the index. */
+cm_printindex ()
+{
+ int item;
+ INDEX_ELT *index;
+ INDEX_ELT **array;
+ char *index_name;
+ int old_inhibitions = inhibit_paragraph_indentation;
+ int previous_filling_enabled_value = filling_enabled;
+
+ close_paragraph ();
+ get_rest_of_line (&index_name);
+
+ index = index_list (index_name);
+ if ((int) index == -1)
+ {
+ line_error ("Unknown index name `%s'", index_name);
+ free (index_name);
+ return;
+ }
+ else
+ free (index_name);
+
+ array = sort_index (index);
+
+ filling_enabled = 0;
+ inhibit_paragraph_indentation = 1;
+ close_paragraph ();
+ add_word ("* Menu:\n\n");
+
+ printing_index = 1;
+ for (item = 0; (index = array[item]); item++)
+ {
+ int real_line_number = line_number;
+
+ /* Let errors generated while making the index entry point back
+ at the line which contains the entry. */
+ line_number = index->defining_line;
+
+ /* If this particular entry should be printed as a "code" index,
+ then wrap the entry with "@code{...}". */
+ if (index->code)
+ execute_string ("* @code{%s}: ", index->entry);
+ else
+ execute_string ("* %s: ", index->entry);
+
+ /* Pad the front of the destination nodename so that
+ the output looks nice. */
+ if (fill_column > 40 && output_column < 40)
+ indent (40 - output_column);
+
+ execute_string ("%s.\n", index->node);
+
+ line_number = real_line_number;
+ flush_output ();
+ }
+
+ printing_index = 0;
+ free (array);
+ close_single_paragraph ();
+ filling_enabled = previous_filling_enabled_value;
+ inhibit_paragraph_indentation = old_inhibitions;
+}
+
+
+/* **************************************************************** */
+/* */
+/* Making User Defined Commands */
+/* */
+/* **************************************************************** */
+
+define_user_command (name, proc, needs_braces_p)
+ char *name;
+ FUNCTION *proc;
+ int needs_braces_p;
+{
+ int slot = user_command_array_len;
+ user_command_array_len++;
+
+ if (!user_command_array)
+ user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
+
+ user_command_array = (COMMAND **) xrealloc (user_command_array,
+ (1 + user_command_array_len) *
+ sizeof (COMMAND *));
+
+ user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
+ user_command_array[slot]->name = savestring (name);
+ user_command_array[slot]->proc = proc;
+ user_command_array[slot]->argument_in_braces = needs_braces_p;
+}
+
+/* Make ALIAS run the named FUNCTION. Copies properties from FUNCTION. */
+define_alias (alias, function)
+ char *alias, *function;
+{
+}
+
+/* Set the paragraph indentation variable to the value specified in STRING.
+ Values can be:
+ `asis': Don't change existing indentation.
+ `none': Remove existing indentation.
+ NUM: Indent NUM spaces at the starts of paragraphs.
+ Note that if NUM is zero, we assume `none'.
+
+ Returns 0 if successful, or non-zero if STRING isn't one of the above. */
+int
+set_paragraph_indent (string)
+ char *string;
+{
+ if (strcmp (string, "asis") == 0)
+ paragraph_start_indent = 0;
+ else if (strcmp (string, "none") == 0)
+ paragraph_start_indent = -1;
+ else
+ {
+ if (sscanf (string, "%d", &paragraph_start_indent) != 1)
+ return (-1);
+ else
+ {
+ if (paragraph_start_indent == 0)
+ paragraph_start_indent = -1;
+ }
+ }
+ return (0);
+}
+
+cm_paragraphindent ()
+{
+ char *arg;
+
+ get_rest_of_line (&arg);
+ if (set_paragraph_indent (arg) != 0)
+ line_error ("Bad argument to @paragraphindent");
+
+ free (arg);
+}
+
+/* Some support for footnotes. */
+
+/* Footnotes are a new construct in Info. We don't know the best method
+ of implementing them for sure, so we present two possiblities.
+
+ SeparateNode:
+ Make them look like followed references, with the reference
+ destinations in a makeinfo manufactured node or,
+
+ EndNode:
+ Make them appear at the bottom of the node that they originally
+ appeared in. */
+#define SeparateNode 0
+#define EndNode 1
+
+int footnote_style = EndNode;
+int first_footnote_this_node = 1;
+int footnote_count = 0;
+
+/* Set the footnote style based on he style identifier in STRING. */
+int
+set_footnote_style (string)
+ char *string;
+{
+ if ((stricmp (string, "separate") == 0) ||
+ (stricmp (string, "MN") == 0))
+ footnote_style = SeparateNode;
+ else if ((stricmp (string, "end") == 0) ||
+ (stricmp (string, "EN") == 0))
+ footnote_style = EndNode;
+ else
+ return (-1);
+
+ return (0);
+}
+
+cm_footnotestyle ()
+{
+ char *arg;
+
+ get_rest_of_line (&arg);
+
+ if (set_footnote_style (arg) != 0)
+ line_error ("Bad argument to @footnotestyle");
+
+ free (arg);
+}
+
+typedef struct fn
+{
+ struct fn *next;
+ char *marker;
+ char *note;
+} FN;
+
+FN *pending_notes = (FN *) NULL;
+
+/* A method for remembering footnotes. Note that this list gets output
+ at the end of the current node. */
+remember_note (marker, note)
+ char *marker, *note;
+{
+ FN *temp = (FN *) xmalloc (sizeof (FN));
+
+ temp->marker = savestring (marker);
+ temp->note = savestring (note);
+ temp->next = pending_notes;
+ pending_notes = temp;
+ footnote_count++;
+}
+
+/* How to get rid of existing footnotes. */
+free_pending_notes ()
+{
+ FN *temp;
+
+ while ((temp = pending_notes) != (FN *) NULL)
+ {
+ free (temp->marker);
+ free (temp->note);
+ pending_notes = pending_notes->next;
+ free (temp);
+ }
+ first_footnote_this_node = 1;
+ footnote_count = 0;
+}
+
+/* What to do when you see a @footnote construct. */
+
+ /* Handle a "footnote".
+ footnote *{this is a footnote}
+ where "*" is the marker character for this note. */
+cm_footnote ()
+{
+ char *marker;
+ char *note;
+
+ get_until ("{", &marker);
+ canon_white (marker);
+
+ /* Read the argument in braces. */
+ if (curchar () != '{')
+ {
+ line_error ("`@%s' expected more than just `%s'. It needs something in `{...}'", command, marker);
+ free (marker);
+ return;
+ }
+ else
+ {
+ int braces = 1;
+ int temp = ++input_text_offset;
+ int len;
+
+ while (braces)
+ {
+ if (temp == size_of_input_text)
+ {
+ line_error ("No closing brace for footnote `%s'", marker);
+ return;
+ }
+
+ if (input_text[temp] == '{')
+ braces++;
+ else if (input_text[temp] == '}')
+ braces--;
+ else if (input_text[temp] == '\n')
+ line_number ++;
+
+ temp++;
+ }
+
+ len = (temp - input_text_offset) - 1;
+ note = (char *)xmalloc (len + 1);
+ strncpy (note, &input_text[input_text_offset], len);
+ note[len] = '\0';
+ input_text_offset = temp;
+ }
+
+ if (!current_node || !*current_node)
+ {
+ line_error ("Footnote defined without parent node");
+ free (marker);
+ free (note);
+ return;
+ }
+
+ if (!*marker)
+ {
+ free (marker);
+
+ if (number_footnotes)
+ {
+ marker = (char *)xmalloc (10);
+ sprintf (marker, "%d", current_footnote_number);
+ current_footnote_number++;
+ }
+ else
+ marker = savestring ("*");
+ }
+
+ remember_note (marker, note);
+
+ /* Your method should at least insert MARKER. */
+ switch (footnote_style)
+ {
+ case SeparateNode:
+ add_word_args ("(%s)", marker);
+ if (first_footnote_this_node)
+ {
+ char *temp_string;
+
+ temp_string = (char *)
+ xmalloc ((strlen (current_node)) + (strlen ("-Footnotes")) + 1);
+
+ add_word_args (" (*note %s-Footnotes::)", current_node);
+ strcpy (temp_string, current_node);
+ strcat (temp_string, "-Footnotes");
+#ifdef TRACK_SRCFILE
+ remember_node_reference (temp_string, line_number, src_lineno, followed_reference);
+#else
+ remember_node_reference (temp_string, line_number, followed_reference);
+#endif /* TRACK_SRCFILE */
+ free (temp_string);
+ first_footnote_this_node = 0;
+ }
+ break;
+
+ case EndNode:
+ add_word_args ("(%s)", marker);
+ break;
+
+ default:
+ break;
+ }
+ free (marker);
+ free (note);
+}
+
+/* Non-zero means that we are currently in the process of outputting
+ footnotes. */
+int already_outputting_pending_notes = 0;
+
+/* Output the footnotes. We are at the end of the current node. */
+output_pending_notes ()
+{
+ FN *footnote = pending_notes;
+
+ if (!pending_notes)
+ return;
+
+ switch (footnote_style)
+ {
+
+ case SeparateNode:
+ {
+ char *old_current_node = current_node;
+ char *old_command = savestring (command);
+
+ already_outputting_pending_notes++;
+ execute_string ("@node %s-Footnotes,,,%s\n", current_node, current_node);
+ already_outputting_pending_notes--;
+ current_node = old_current_node;
+ free (command);
+ command = old_command;
+ }
+ break;
+
+ case EndNode:
+ close_paragraph ();
+ in_fixed_width_font++;
+ execute_string ("---------- Footnotes ----------\n\n");
+ in_fixed_width_font--;
+ break;
+ }
+
+ /* Handle the footnotes in reverse order. */
+ {
+ FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
+
+ array[footnote_count] = (FN *) NULL;
+
+ while (--footnote_count > -1)
+ {
+ array[footnote_count] = footnote;
+ footnote = footnote->next;
+ }
+
+ filling_enabled = 1;
+ indented_fill = 1;
+
+ while (footnote = array[++footnote_count])
+ {
+
+ switch (footnote_style)
+ {
+ case SeparateNode:
+ case EndNode:
+ execute_string ("(%s) %s", footnote->marker, footnote->note);
+ close_paragraph ();
+ break;
+ }
+ }
+ close_paragraph ();
+ free (array);
+ }
+}
+
+
+/* **************************************************************** */
+/* */
+/* User definable Macros (text substitution) */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_MACROS)
+
+/* Array of macros and definitions. */
+MACRO_DEF **macro_list = (MACRO_DEF **)NULL;
+
+int macro_list_len = 0; /* Number of elements. */
+int macro_list_size = 0; /* Number of slots in total. */
+
+/* Return the macro definition of NAME or NULL if NAME is not defined. */
+MACRO_DEF *
+find_macro (name)
+ char *name;
+{
+ register int i;
+ register MACRO_DEF *def;
+
+ def = (MACRO_DEF *)NULL;
+ for (i = 0; macro_list && (def = macro_list[i]); i++)
+ if (strcmp (def->name, name) == 0)
+ break;
+
+ return (def);
+}
+
+/* Add the macro NAME with DEFINITION to macro_list. FILENAME is
+ the name of the file where this definition can be found, and
+ LINENO is the line number within that file. If a macro already
+ exists with NAME, then a warning is produced, and that previous
+ definition is overwritten. */
+void
+add_macro (name, definition, filename, lineno)
+ char *name, *definition;
+ char *filename;
+ int lineno;
+{
+ register MACRO_DEF *def;
+
+ def = find_macro (name);
+
+ if (!def)
+ {
+ if (macro_list_len + 2 >= macro_list_size)
+ macro_list = (MACRO_DEF **)xrealloc
+ (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *)));
+
+ macro_list[macro_list_len] = (MACRO_DEF *)xmalloc (sizeof (MACRO_DEF));
+ macro_list[macro_list_len + 1] = (MACRO_DEF *)NULL;
+
+ def = macro_list[macro_list_len];
+ macro_list_len += 1;
+ def->name = savestring (name);
+ }
+ else
+ {
+ char *temp_filename = input_filename;
+ int temp_line = line_number;
+
+ warning ("The macro `%s' is previously defined.", name);
+
+ input_filename = def->filename;
+ line_number = def->lineno;
+
+ warning ("Here is the previous definition of `%s'.", name);
+
+ input_filename = temp_filename;
+ line_number = temp_line;
+
+ free (def->filename);
+ free (def->definition);
+ }
+
+ def->filename = savestring (filename);
+ def->lineno = lineno;
+ def->definition = savestring (definition);
+}
+
+
+/* Delete the macro with name NAME. The macro is deleted from the list,
+ but it is also returned. If there was no macro defined, NULL is
+ returned. */
+MACRO_DEF *
+delete_macro (name)
+ char *name;
+{
+ register int i;
+ register MACRO_DEF *def;
+
+ def = (MACRO_DEF *)NULL;
+ for (i = 0; macro_list && (def = macro_list[i]); i++)
+ if (strcmp (def->name, name) == 0)
+ {
+ bcopy (macro_list + i + 1, macro_list + i,
+ ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *));
+ break;
+ }
+ return (def);
+}
+
+/* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
+void
+execute_macro (def)
+ MACRO_DEF *def;
+{
+
+ if (def != (MACRO_DEF *)NULL)
+ {
+ char *line, *string;
+
+ get_until ("\n", &line);
+
+ if (curchar () == '\n') /* as opposed to the end of the file... */
+ {
+ line_number++;
+ input_text_offset++;
+ }
+ string = (char *)xmalloc (1 + strlen (def->definition) + strlen (line));
+ strcpy (string, def->definition);
+ strcat (string, line);
+ free (line);
+
+ execute_string ("%s\n", string);
+ free (string);
+ }
+}
+
+int
+cm_macro ()
+{
+ register int i;
+ char *line, *name, *expansion;
+
+ get_rest_of_line (&line);
+ canon_white (line);
+
+ for (i = 0; line[i] && !whitespace (line[i]); i++);
+ name = (char *)xmalloc (i);
+ strncpy (name, line, i);
+ name[i] = '\0';
+
+ while (whitespace (line[i]))
+ i++;
+
+ add_macro (name, line + i, input_filename, line_number - 1);
+ free (line);
+ free (name);
+}
+
+int
+cm_unmacro ()
+{
+ register int i;
+ char *line, *name;
+ MACRO_DEF *def;
+
+ get_rest_of_line (&line);
+ canon_white (line);
+
+ for (i = 0; line[i] && !whitespace (line[i]); i++);
+ name = (char *)xmalloc (i);
+ strncpy (name, line, i);
+ name[i] = '\0';
+
+ def = delete_macro (name);
+
+ if (def)
+ {
+ free (def->filename);
+ free (def->name);
+ free (def->definition);
+ free (def);
+ }
+
+ free (line);
+ free (name);
+}
+#endif /* HAVE_MACROS */
+
+/* **************************************************************** */
+/* */
+/* Looking For Include Files */
+/* */
+/* **************************************************************** */
+
+/* Given a string containing units of information separated by colons,
+ return the next one pointed to by INDEX, or NULL if there are no more.
+ Advance INDEX to the character after the colon. */
+char *
+extract_colon_unit (string, index)
+ char *string;
+ int *index;
+{
+ int i, start;
+
+ i = *index;
+
+ if (!string || (i >= strlen (string)))
+ return ((char *)NULL);
+
+ /* Each call to this routine leaves the index pointing at a colon if
+ there is more to the path. If I is > 0, then increment past the
+ `:'. If I is 0, then the path has a leading colon. Trailing colons
+ are handled OK by the `else' part of the if statement; an empty
+ string is returned in that case. */
+ if (i && string[i] == ':')
+ i++;
+
+ start = i;
+
+ while (string[i] && string[i] != ':') i++;
+
+ *index = i;
+
+ if (i == start)
+ {
+ if (string[i])
+ (*index)++;
+
+ /* Return "" in the case of a trailing `:'. */
+ return (savestring (""));
+ }
+ else
+ {
+ char *value;
+
+ value = (char *)xmalloc (1 + (i - start));
+ strncpy (value, &string[start], (i - start));
+ value [i - start] = '\0';
+
+ return (value);
+ }
+}
+
+/* Return the full pathname for FILENAME by searching along PATH.
+ When found, return the stat () info for FILENAME in FINFO.
+ If PATH is NULL, only the current directory is searched.
+ If the file could not be found, return a NULL pointer. */
+char *
+get_file_info_in_path (filename, path, finfo)
+ char *filename, *path;
+ struct stat *finfo;
+{
+ char *dir;
+ int result, index = 0;
+
+ if (path == (char *)NULL)
+ path = ".";
+
+ /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
+ if (*filename == '/' ||
+ (*filename == '.' &&
+ (filename[1] == '/' ||
+ (filename[1] == '.' && filename[2] == '/'))))
+ {
+ if (stat (filename, finfo) == 0)
+ return (savestring (filename));
+ else
+ return ((char *)NULL);
+ }
+
+ while (dir = extract_colon_unit (path, &index))
+ {
+ char *fullpath;
+
+ if (!*dir)
+ {
+ free (dir);
+ dir = savestring (".");
+ }
+
+ fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename));
+ sprintf (fullpath, "%s/%s", dir, filename);
+ free (dir);
+
+ result = stat (fullpath, finfo);
+
+ if (result == 0)
+ return (fullpath);
+ else
+ free (fullpath);
+ }
+ return ((char *)NULL);
+}
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.texinfo b/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.texinfo
new file mode 100644
index 0000000000..81f3796fb0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/makeinfo.texinfo
@@ -0,0 +1,226 @@
+\include texinfo.tex @c -*- texinfo -*-
+
+@setfilename makeinfo.info
+
+@node Top
+@chapter What is Makeinfo?
+
+Makeinfo is a program for converting @dfn{texinfo} files into @dfn{info}
+files. Texinfo is a documentation language which allows a printed manual
+and online documentation (an info file) to be produced from a single source
+file.
+
+This text does not explain how to write a texinfo file. In order to
+usefully use this documentation, you should be familiar with the texinfo
+documentation language, and you should have used an info file reader to
+read some info files. A good place to start is with @code{info}, a program
+for reading online documentation. Just type @code{info} to get started.
+Documentation on the texinfo language is available in the node Texinfo.
+Type @code{info texinfo} to read it.
+
+@menu
+* Formatting Control:: Controlling the appearance of the output file.
+* Options:: Command line options.
+* Validation:: What makes a `valid' info file.
+* Node Defaulting:: How Makeinfo can fill in the node fields for you.
+@end menu
+
+@node Formatting Control
+@section Controlling Paragraph Formats
+
+In general, Makeinfo @dfn{fills} the paragraphs that it outputs to the info
+file. Filling is the process of breaking up and connecting lines such that
+the output is nearly justified. With Makeinfo, you can control:
+
+@itemize @bullet
+@item
+The width of the paragraph (the @dfn{fill-column}).
+@item
+The amount of indentation that the first line of the paragraph gets (the
+@dfn{paragraph-indentation}).
+@end itemize
+
+
+@node Options
+@section Command Line Options
+
+The following command line options are available for Makeinfo.
+
+@table @code
+
+@item +error-limit @var{num}
+Sets the maximum number of errors that Makeinfo will print before exiting
+(on the assumption that continuing would be useless). The default number
+of errors that can be printed before Makeinfo gives up on processing the
+input file is 100.
+
+@item +fill-column @var{num}
+Specifies the maximum right-hand edge of a line. Paragraphs that are
+filled will be filled to this width. The default value for fill-column
+is 72.
+
+@item +footnote-style @var{style}
+
+Sets the footnote style to @var{style}. @var{style} should either be `MN'
+for `make node', or `EN' for `bottom node'. When the footnote style is
+`MN', Makeinfo makes a new node containing the footnotes found in the
+current node. When the footnote style is `EN', Makeinfo places the
+footnote references at the end of the current node.
+
+@item +no-split
+Suppress the splitting stage of Makeinfo. In general, large output files
+(where the size is greater than 70k bytes) are split into smaller subfiles,
+each one apporximately 50k bytes. By specifying @code{+no-split}, Makeinfo
+will not split up the output file.
+
+@item +no-validate
+Suppress the validation phase of Makeinfo. Normally, after the file is
+processed, some consistency checks are made to ensure that cross references
+can be resolved, etc. @xref{Validation}.
+
+@item +no-warn
+Suppress the output of warning messages. This does @emph{not} suppress the
+output of error messages, simply warnings. You might want this if the file
+you are creating has texinfo examples in it, and the nodes that are
+referenced don't actually exist.
+
+@item +no-number-footnotes
+Supress the automatic numbering of footnotes. The default is number
+each footnote sequentially in a single node, resetting the current
+footnote number to 1 at the start of each node.
+
+@item +paragraph-indent @var{num}
+Sets the paragraph indentation to @var{num}. The value of @var{num} is
+interpreted as follows:
+
+@itemize @bullet
+@item
+A value of 0 means don't change the existing indentation at the starts of
+paragraphs.
+@item
+A value less than zero means indent paragraph starts to column zero by
+deleting the existing indentation.
+@item
+A value greater than zero is the number of spaces to leave at the front of
+each paragraph start.
+@end itemize
+
+@item +verbose
+Causes Makeinfo to inform you as to what it is doing. Normally Makeinfo
+only outputs text if there are errors or warnings.
+
+@item +version
+Prints outs the version number of Makeinfo.
+
+@end table
+
+@node Validation
+@section What makes a valid Info file?
+
+If you have not suppressed validation (with the @code{+no-validate}
+option), Makeinfo will check the validity of the final info file. Mostly,
+this means ensuring that nodes you have referenced really exist. Here is a
+complete list of what is checked:
+
+@enumerate
+@item
+If a node reference such as Prev, Next or Up is a reference to a node in
+this file (i.e., not an external reference such as `(DIR)'), then the
+referenced node must exist.
+
+@item
+In a given node, if the node referenced by the Prev is different than the
+node referenced by the Up, then the node referenced by the Prev must have a
+Next which references this node.
+
+@item
+Every node excepting @code{Top} must have an Up field.
+
+@item
+The node referenced by Up must contain a reference to this node, other than
+a Next reference. Obviously, this includes menu items and followed
+references.
+
+@item
+If the Next reference is not the same as the Next reference of the Up
+reference, then the node referenced by Next must have a Prev reference
+pointing back at this node. This rule still allows the last node in a
+section to point to the first node of the next chapter.
+
+@end enumerate
+
+@node Node Defaulting
+@section Defaulting the @code{Prev}, @code{Next}, and @code{Up}
+
+Although the definition of an info file allows a great deal of
+flexibility, there are some conventions that you are urged to follow.
+By letting Makeinfo default the Next, Prev, and Up pointers you can
+follow these conventions with the minimum of effort.
+
+A common error ocurrs when adding a new node to a menu; often the nodes
+which are referenced in the menu do not point to each other in the same
+order as they appear in the menu.
+
+Makeinfo helps with this particular problem by defaulting Next, Prev, and
+Up pointers in a @code{@@node} command if you leave off these pointers in
+the command.
+
+The node to receive the defaulted pointers must be followed immediately by
+a sectioning command, such as @code{@@chapter} or @code{@@section}, and
+must appear in a menu that is one sectioning level or more above the
+sectioning level that this node is to have.
+
+Here is an example of using this feature.
+
+@example
+@@setfilename default-nodes-example.info
+@@node Top
+@@chapter Introduction
+@@menu
+* foo:: the foo node
+* bar:: the bar node
+@@end menu
+
+@@node foo
+@@section foo
+this is the foo node.
+
+@@node bar
+@@section Bar
+This is the Bar node.
+@@bye
+
+@end example
+
+produces
+
+@example
+Info file default-nodes-example.info, produced by Makeinfo, -*- Text -*-
+from input file default-nodes.texinfo.
+
+File: default-nodes-example.info, Node: Top
+
+Introduction
+************
+
+* Menu:
+
+* foo:: the foo node
+* bar:: the bar node
+
+File: default-nodes-example.info, Node: foo, Next: bar, Up: Top
+
+foo
+===
+
+this is the foo node.
+
+File: default-nodes-example.info, Node: bar, Prev: foo, Up: Top
+
+Bar
+===
+
+This is the Bar node.
+
+@end example
+@bye
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/postmakeinfo.prl b/web/glasgow/lit2x-0.16/literate/info-utils/postmakeinfo.prl
new file mode 100644
index 0000000000..81eaad12b0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/postmakeinfo.prl
@@ -0,0 +1,81 @@
+#
+die "must have exactly one argument\n" if $#ARGV != 0;
+die "input file $ARGV[0] doesn't exist\n" if ! -f $ARGV[0];
+$Inputfile = $ARGV[0];
+$Bakfile = $ARGV[0].'.bak';
+
+rename($Inputfile, $Bakfile) ||
+ die "Can't rename $Inputfile to $Bakfile\n";
+
+sub put_file_back {
+ print STDERR "doing mv $Bakfile $Inputfile...\n";
+ rename($Bakfile, $Inputfile) ||
+ die "Can't rename $Bakfile to $Inputfile\n";
+ exit(1);
+}
+$SIG{'INT'} = 'put_file_back';
+$SIG{'QUIT'} = 'put_file_back';
+
+open(OUTF,">$Inputfile") || die "Can't re-open $Inputfile for output\n";
+select(OUTF);
+
+$ARGV[0] = $Bakfile; # fiddle with, before first <> read
+
+# NB: eof() == 1 in perl means NEXT read will return end-of-file (urgh)
+
+$_ = <>;
+
+while ( $_ ) { # I don't dig this test ...
+
+ # loop-'n-echo 'til we find a menu
+ while ( $_ && ! /^\* Menu:/) {
+ print $_;
+ $_ = <>;
+ }
+ next if ! /^\* Menu:/;
+
+ # we found a menu, so munge it...
+ print $_; # the *Menu:...
+
+ # snarf the entries (everything 'til node ends), rm'ing exact duplicates
+ # and uniquifying diff ones with the same
+ # entry part
+ # (they are sorted, right ?)
+
+ $prev_entry = '';
+ $prev_nodename = '';
+ $uniquer = 2;
+ $_ = <>;
+
+ while ( $_ && ! /^\037/) {
+
+ if (/^\*(\s*)([^:]*)(:\s*)(.*)$/) {
+ $indent = $1;
+ $divider = $3;
+ $nodename = $4;
+ # fix the @_sep_@ stuff...
+ ($entry = $2) =~ s/(.+)\@_sep_\@//;
+
+ next if $entry eq $prev_entry && $nodename eq $prev_nodename;
+
+ if ($entry eq $prev_entry) {
+ print "\*${indent}${entry}_${uniquer}${divider}${nodename}\n";
+ $uniquer++;
+ } else {
+ print "\*${indent}${entry}${divider}${nodename}\n";
+ $uniquer = 2; # reset
+ }
+
+ } else { # comment line
+ print $_;
+ }
+ } continue {
+ $_ = <>; # next...
+ $prev_entry = $entry;
+ $prev_nodename = $nodename;
+ }
+}
+close(OUTF);
+
+# once we're brave:
+#unlink $Bakfile;
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/test-suite.texinfo b/web/glasgow/lit2x-0.16/literate/info-utils/test-suite.texinfo
new file mode 100644
index 0000000000..cf0ea3256c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/test-suite.texinfo
@@ -0,0 +1,167 @@
+Info file: TEST-elisp-file, -*-Text-*-
+produced by texinfo-format-buffer
+from file: test.texinfo
+
+Examples of @def's
+******************
+
+* Command: revert-buffer &optional NO-AUTOSAVE-OFFER-P NOCONFIRM
+
+ This command replaces the buffer text with the text of the
+ visited file on disk. This action undoes all changes since the
+ file was visited or saved. If the latest auto-save file is more
+ recent than the visited file, Emacs asks the user whether to use
+ that instead.
+
+ When the value of the `no-autosave-offer-p' argument is
+ non-`nil', Emacs does not offer to use the auto-save file. This
+ argument is the prefix argument when the function is called
+ interactively.
+
+ When the value of the `noconfirm' argument is non-`nil', emacs
+ does not ask for confirmation for the reversion action. This means
+ that the buffer is deleted and replaced by the text from the file
+ on the disk without asking the user if he or she really want that.
+
+ If the value of the `revert-buffer-function' variable is
+ non-`nil', it is called as a function to do the work.
+
+* Function: cons OBJECT1 OBJECT2
+
+ This function is the primary function used to build new lists.
+ It creates a new cons cell, making OBJECT1 the `car', and OBJECT2
+ the `cdr'. It then returns a pointer to the new cons cell. There
+ is no requirement for OBJECT2 to be of any particular type,
+ although it is normally a list.
+
+ (cons 1 '(2))
+ => (1 2)
+ (cons 1 '())
+ => (1)
+ (cons 1 2)
+ => (1 . 2)
+
+* Function: list &rest OBJECTS
+
+ This function creates a list with OBJECTS as its elements. The
+ resulting list is always `nil'-terminated. If no OBJECTS are
+ given, the empty list is returned.
+
+ (list 1 2 3 4 5)
+ => (1 2 3 4 5)
+ (list)
+ => nil
+
+
+* Special form: progn FORMS...
+
+ This special form evaluates all of the FORMS, in textual order,
+ returning the result of the final form.
+
+ (progn (print "The first form")
+ (print "The second form")
+ (print "The third form"))
+ -| "The first form"
+ -| "The second form"
+ -| "The third form"
+ => "The third form"
+
+* Variable: obarray
+
+ This global variable is the standard obarray for use by `intern'
+ and `read'. It is a vector whose length ought to be prime for best
+ results (presently 511). Each element is an interned symbol whose
+ name hashes to that bucket. That symbol (if any) has an internal
+ link (invisible to the user) to the next symbol that hashes to that
+ bucket. The order of these is unimportant.
+
+
+================================================================
+
+
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename TEST-elisp-file
+@settitle GNU Emacs Lisp TEST File
+@c %**end of header
+
+@unnumbered Examples of @@def's
+
+@deffn Command revert-buffer &optional no-autosave-offer-p noconfirm
+ This command replaces the buffer text with the text of the visited
+file on disk. This action undoes all changes since the file was
+visited or saved. If the latest auto-save file is more recent than the
+visited file, Emacs asks the user whether to use that instead.
+
+ When the value of the @code{no-autosave-offer-p} argument is
+non-@code{nil}, Emacs does not offer to use the auto-save file. This
+argument is the prefix argument when the function is called
+interactively.
+
+ When the value of the @code{noconfirm} argument is non-@code{nil},
+emacs does not ask for confirmation for the reversion action. This
+means that the buffer is deleted and replaced by the text from the
+file on the disk without asking the user if he or she really want that.
+
+ If the value of the @code{revert-buffer-function} variable is
+non-@code{nil}, it is called as a function to do the work.
+@end deffn
+
+@defun cons object1 object2
+ This function is the primary function used to build new lists. It creates
+a new cons cell, making @var{object1} the @code{car}, and @var{object2} the
+@code{cdr}. It then returns a pointer to the new cons cell. There is no
+requirement for @var{object2} to be of any particular type, although it is
+normally a list.
+
+@example
+(cons 1 '(2))
+ @result{} (1 2)
+(cons 1 '())
+ @result{} (1)
+(cons 1 2)
+ @result{} (1 . 2)
+@end example
+@end defun
+
+@defun list &rest objects
+ This function creates a list with @var{objects} as its elements. The
+resulting list is always @code{nil}-terminated. If no @var{objects}
+are given, the empty list is returned.
+
+@example
+(list 1 2 3 4 5)
+ @result{} (1 2 3 4 5)
+(list)
+ @result{} nil
+@end example
+@end defun
+
+
+@defspec progn forms@dots{}
+This special form evaluates all of the @var{forms}, in textual
+order, returning the result of the final form.
+
+@example
+(progn (print "The first form")
+ (print "The second form")
+ (print "The third form"))
+ @print{} "The first form"
+ @print{} "The second form"
+ @print{} "The third form"
+ @result{} "The third form"
+@end example
+@end defspec
+
+@defvar obarray
+ This global variable is the standard obarray for use by @code{intern} and
+@code{read}. It is a vector whose length ought to be prime for best
+results (presently 511). Each element is an interned symbol whose name
+hashes to that bucket. That symbol (if any) has an internal link (invisible
+to the user) to the next symbol that hashes to that bucket. The order of
+these is unimportant.
+@end defvar
+
+
+@bye
+
diff --git a/web/glasgow/lit2x-0.16/literate/info-utils/testfile.texinfo b/web/glasgow/lit2x-0.16/literate/info-utils/testfile.texinfo
new file mode 100644
index 0000000000..a7d924448f
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/info-utils/testfile.texinfo
@@ -0,0 +1,130 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename format-test-file
+@settitle Formatting Test File
+@c %**end of header
+
+
+@unnumberedsec Formatting Command Test File
+
+This file tests the following commands:
+
+@example
+result
+expansion
+prints
+equiv
+
+deffn
+defun
+defspec
+defvar
+@end example
+
+@c result
+@c
+The following example tests @code{@@result@{@}}
+
+@example
+(car '(bow midships stern)) ; @r{This is a comment using @@r@{}
+@result{} bow ; @r{This is an aligned comment using @@r@{}
+@end example
+
+@c expansion
+@c
+The following example tests @code{@@expansion@{@}} and @code{@@result@{@}}
+
+@example
+(third '(a b c)) ; @r{This is a comment using @@r@{}
+@expansion{} (car (cdr (cdr '(a b c)))) ; @r{This is an aligned comment.}
+@result{} c ; @r{This is an aligned comment.}
+@end example
+
+@c print
+@c
+The following example tests @code{@@prints@{@}}
+
+@example
+(message "Hello.") ; @r{This is a comment using @@r@{}
+@print{} Hello. ; @r{This is an aligned comment using @@r@{}
+@end example
+
+@c equiv
+@c
+The following example tests @code{@@equiv@{@}}
+
+@example
+(make-sparse-keymap) @equiv{} (list 'keymap)
+@end example
+
+@c error
+@c
+The following example tests @code{@@error@{@}}
+
+@example
+(car)
+@error{} Wrong number of arguments: #<subr car>, 0
+@end example
+
+@c indentedresult
+@c
+The following example tests @code{@@result@{@}}
+
+This command is an experiment designed to make it easy to change
+indentation until we get it right.
+
+@example
+(car '(bow midships stern))
+ @result{} bow
+@end example
+
+@c indentedexpansion, indendedresult
+@c
+The following example tests
+@code{@@expansion@{@}} and @code{@@result@{@}}
+
+@example
+(third '(a b c))
+ @expansion{} (car (cdr (cdr '(a b c))))
+ @result{} c
+@end example
+
+
+@subheading @@def commands
+
+@deffn Command make-variable-buffer-local symbol
+This function marks @var{symbol} automatically buffer local, so that
+any attempt to set it will make it local to the current buffer at the
+time.
+
+ I put this here twice on purpose: this function marks @var{symbol}
+automatically buffer local, so that any attempt to set it will make it
+local to the current buffer at the time.
+
+The value returned is @var{symbol}.
+@end deffn
+
+@defun default-value symbol
+Return @var{symbol}'s default value. This is the value that is seen
+in buffers that do not have their own values for this variable. If
+@var{symbol} is not buffer-local, than this is the same as
+@code{symbol-value} (@pxref{Accessing Variables}).
+@end defun
+
+@defspec setq-default symbol value
+This function sets the default (global) value of @var{symbol} to
+@var{value}. @var{symbol} is not evaluated, but @var{value} is. The
+value of the @code{setq-default} form is @var{value}.
+
+@dots{}
+@end defspec
+
+@defvar minibuffer-completion-table
+ The value of this variable is the alist or obarray used for
+completion in the minibuffer. This is the global variable that
+contains what @code{completing-read} passes to @code{read-minibuffer}.
+It is used by all the minibuffer completion functions, such as
+@code{minibuffer-complete-word}.
+@end defvar
+
+@bye
diff --git a/web/glasgow/lit2x-0.16/literate/leathrum_on_pgm_typesetting.tex b/web/glasgow/lit2x-0.16/literate/leathrum_on_pgm_typesetting.tex
new file mode 100644
index 0000000000..fc99506efe
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/leathrum_on_pgm_typesetting.tex
@@ -0,0 +1,59 @@
+% From: leathrum@dartmouth.edu (Thomas E. Leathrum)
+% Newsgroups: comp.text.tex
+% Subject: Re: WEB
+% Date: 26 Feb 90 00:44:03 GMT
+% Organization: Dartmouth College, Hanover, NH
+%
+% I haven't been paying a whole lot of attention to the messages about
+% typesetting computer programs, but one I read had an interesting idea: reverse
+% the typefaces, leaving reserved words in plain face and putting variable and
+% procedure names in boldface instead. (The argument went something like this:
+% reserved words are a computer language's fancy idea of punctuation, and besides
+% not really as important as the variables and such, so why not turn things
+% around?) Well, I tried this idea out by typesetting a little procedure from
+% Jensen and Wirth's Pascal User Manual and Report, and I'm convinced -- it
+% really looks better! So, for your perusal, I enclose below a little plainTeX
+% file with a Pascal procedure to find and print the largest and smallest entries
+% in an array of n integers.
+%
+% Regards,
+% Tom Leathrum
+% moth@dartmouth.edu
+%
+% ---------------------------------------
+%
+% >From Program 11.1 p.68 in 2nd edition
+%
+\+ procedure {\bf minmax};\cr
+\+ var {\bf i}: 1..{\bf n};\cr
+\+ \quad {\bf u}, {\bf v}, {\bf min}, {\bf max}: integer;\cr
+\+ begin\cr
+\+ \quad {\bf min}$:=${\bf a}[1];\cr
+\+ \quad {\bf max}$:=${\bf min};\cr
+\+ \quad while {\bf i}$<${\bf n} do\cr
+\+ \quad begin\cr
+\+ \quad \quad {\bf u}$:=${\bf a}[{\bf i}];\cr
+\+ \quad \quad {\bf v}$:=${\bf a}[{\bf i}$+1$];\cr
+\+ \quad \quad if {\bf u}$>${\bf v} then\cr
+\+ \quad\quad begin\cr
+\+ \quad \quad\quad if {\bf u}$>${\bf max} then {\bf max}$:=${\bf u};\cr
+\+ \quad \quad\quad if {\bf v}$<${\bf min} then {\bf min}$:=${\bf u};\cr
+\+ \quad\quad end;\cr
+\+ \quad \quad else\cr
+\+ \quad\quad begin\cr
+\+ \quad \quad\quad if {\bf v}$>${\bf max} then {\bf max}$:=${\bf v};\cr
+\+ \quad \quad\quad if {\bf u}$<${\bf min} then {\bf min}$:=${\bf u};\cr
+\+ \quad\quad end;\cr
+\+ \quad \quad {\bf i}$:=${\bf i}$+2$;\cr
+\+ \quad end;\cr
+\+ \quad if {\bf i}$=${\bf n} then\cr
+\+ \quad \quad if {\bf a}[{\bf n}]$>${\bf max} then
+ {\bf max}$:=${\bf a}[{\bf n}];\cr
+\+ \quad else\cr
+\+ \quad \quad if {\bf a}[{\bf n}]$<${\bf min} then
+ {\bf min}$:=${\bf a}[{\bf n}];\cr
+\+ \quad {\bf writeln}({\bf min}, {\bf max});\cr
+\+ \quad {\bf writeln};\cr
+\+ end;\cr
+
+\end
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2changes.lprl b/web/glasgow/lit2x-0.16/literate/lit-2changes.lprl
new file mode 100644
index 0000000000..e2ba6ae7ab
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2changes.lprl
@@ -0,0 +1,6 @@
+\section[lit2changelog_only]{Code used only in extracting changelogs}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2depend.lprl b/web/glasgow/lit2x-0.16/literate/lit-2depend.lprl
new file mode 100644
index 0000000000..b6711cdb10
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2depend.lprl
@@ -0,0 +1,56 @@
+\section[lit2depend_code]{Code used only in generating dependencies}
+
+\begin{code}
+sub collect_dependencies {
+ local($file_seen) = @_;
+
+ # assuming we're checking dependencies for Input_file "foo.lit"
+ # and we've just seen file "bar.lprl" (for example), we want a
+ # dependencies of the form:
+ # foo.texi: bar.itxi
+ # foo.tex : bar.itex
+
+ local($file_seen_root,$file_seen_suff) = &root_and_suffix($file_seen);
+
+ if ($Inputfile_root ne $file_seen_root) {
+ push(@Depend_lines, "$Inputfile_root.texi : $file_seen_root.itxi\n");
+ push(@Depend_lines, "$Inputfile_root.tex : $file_seen_root.itex\n");
+ }
+}
+
+sub mangle_Makefile { # insert dependencies into Makefile
+ # this really should be made to work just like other mkdepend scripts
+ local($Makefile) = 'Makefile';
+ local($begin_magic_str) = "# DO NOT DELETE: Beginning of literate-docs dependencies\n";
+ local($end_magic_str) = "# DO NOT DELETE: End of literate-docs dependencies\n";
+
+ unlink("$Makefile.bak");
+ rename($Makefile,"$Makefile.bak");
+ # now copy Makefile.bak into Makefile, rm'ing old dependencies
+ # and adding the new
+ open(OMKF,"< $Makefile.bak") || die "$Pgm: can't open $Makefile.bak: $!\n";
+ open(NMKF,"> $Makefile") || die "$Pgm: can't open $Makefile: $!\n";
+ select(NMKF);
+ $_ = <OMKF>;
+ while ($_ && $_ ne $begin_magic_str) { # copy through, 'til begin_magic_str
+ print $_;
+ $_ = <OMKF>;
+ }
+ while ($_ && $_ ne $end_magic_str) { # delete 'til end_magic_str
+ $_ = <OMKF>;
+ }
+ # insert dependencies
+ print $begin_magic_str;
+ print @Depend_lines;
+ print $end_magic_str;
+ while (<OMKF>) { # copy the rest through
+ print $_;
+ }
+ close(NMKF);
+ close(OMKF);
+ chmod 0444, 'Makefile';
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-c.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-c.lprl
new file mode 100644
index 0000000000..c1bc9f6c6b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-c.lprl
@@ -0,0 +1,122 @@
+\section[lit2doc_for_c]{Document-processing code for language \tr{c}}
+
+\begin{code}
+sub rm_embedded_stuff { # return clean code + index entries (\002 separated)
+ local($codetxt) = @_;
+
+ ($codetxt, '');
+}
+
+sub add_code_interests { # DO NOTHING
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($defs_to_return) = '';
+ local($uses_to_return) = '';
+
+ &setup_C_keywords();
+
+ $* = 1; # multi-line searches
+ s/^>//g; # de-Bird-ize
+ s/\/\*[^\/]*\*\///g;# de-commentize (necessarily fraught with peril)
+ s/\"[^\"\n]*\"//g; # de-string-ize and de-char-ize
+ s/\'[^\'\n]*\'//g;
+
+ # OK, the "interesting" DEFS are #define'd things
+ # and things that might be subroutine defns. (3 chars long or more)
+ # The latter must begin in col 1!
+
+ while (/^(\s*#define\s+)([A-Za-z_][A-Za-z0-9_]{2,})(\s*)/ ||
+ /^([A-Z][a-z]+\s+)?([A-Za-z_][A-Za-z0-9_]{2,})(\([A-Za-z0-9_, ]*\))/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # see hacks below
+ local($after) = $3;
+
+#print STDERR "defs=>$before::$interesting_thing::$after::\n";
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_defd[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_defd[$s] .= "$really_interesting_thing\001";
+ } else {
+ $defs_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ # escaping all magic chars in before/interesting/after
+ # is v important for avoiding infinite loops! (also below)
+ $before =~ s/\s+/\\s\+/g;
+ $after =~ s/\s+/\\s\+/g;
+ $after =~ s/\(/\\\(/;
+ $after =~ s/\)/\\\)/;
+
+ s/$before$interesting_thing$after//g;
+ }
+
+ # I AM NOT INTERESTED IN USES AT THE MOMENT
+ if ( 0 ) {
+ # uses are the same sorts of things
+ while (/^(#if\s+|#elif\s+|#else\s+)([A-Za-z_][A-Za-z0-9_]{2,})(\s*)/ || # CPP-ery
+ /(\s*)([A-Za-z_][A-Za-z0-9_]{2,})(\s*)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # more hacks below
+ local($after) = $3;
+
+ #print STDERR "uses=>$before::$interesting_thing::$after::\n";
+
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_used[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_used[$s] .= "$really_interesting_thing\001";
+ } else {
+ $uses_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ $before =~ s/\s+/\\s\+/g;
+ $interesting_thing =~ s/\$/\\\$/;
+ $interesting_thing =~ s/\@/\\\@/;
+ $interesting_thing =~ s/\%/\\\%/;
+ $after =~ s/\s+/\\s\+/g;
+
+ s/$before$interesting_thing$after//g;
+ }
+ }
+ $* = 0;
+
+ ($defs_to_return, $uses_to_return);
+}
+
+sub setup_C_keywords {
+ $IGNORE_WD{'auto'} = 1;
+ $IGNORE_WD{'break'} = 1;
+ $IGNORE_WD{'case'} = 1;
+ $IGNORE_WD{'char'} = 1;
+ $IGNORE_WD{'continue'} = 1;
+ $IGNORE_WD{'default'} = 1;
+ $IGNORE_WD{'do'} = 1;
+ $IGNORE_WD{'double'} = 1;
+ $IGNORE_WD{'else'} = 1;
+ $IGNORE_WD{'entry'} = 1;
+ $IGNORE_WD{'extern'} = 1;
+ $IGNORE_WD{'float'} = 1;
+ $IGNORE_WD{'for'} = 1;
+ $IGNORE_WD{'goto'} = 1;
+ $IGNORE_WD{'if'} = 1;
+ $IGNORE_WD{'int'} = 1;
+ $IGNORE_WD{'long'} = 1;
+ $IGNORE_WD{'register'} = 1;
+ $IGNORE_WD{'return'} = 1;
+ $IGNORE_WD{'short'} = 1;
+ $IGNORE_WD{'sizeof'} = 1;
+ $IGNORE_WD{'static'} = 1;
+ $IGNORE_WD{'struct'} = 1;
+ $IGNORE_WD{'switch'} = 1;
+ $IGNORE_WD{'typedef'} = 1;
+ $IGNORE_WD{'union'} = 1;
+ $IGNORE_WD{'unsigned'} = 1;
+ $IGNORE_WD{'while'} = 1;
+# $IGNORE_WD{''} = 1;
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-f.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-f.lprl
new file mode 100644
index 0000000000..e49a32ab31
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-f.lprl
@@ -0,0 +1,154 @@
+\section[lit2doc_for_f]{Document-processing code for language \tr{Fortran}}
+
+\begin{code}
+
+sub rm_embedded_stuff { # return clean code + index entries (\002 separated)
+ local($codetxt) = @_;
+
+ ($codetxt, '');
+}
+
+\end{code}
+
+\begin{code}
+sub add_code_interests { # DO NOTHING
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($defs_to_return) = '';
+ local($uses_to_return) = '';
+
+ &setup_fortran_keywords();
+
+ $* = 1; # multi-line searches
+ s/^>//g; # de-Bird-ize
+ s/^C.*$//g; # de-commentize
+# s/([^\\\n])!.*$/\1/g; Is this valid ????? ! comment
+ s/\"[^\"\n]*\"//g; # de-stringize
+ s/\'[^\'\n]*\'//g;
+
+ # OK, the "interesting" DEFS are subroutines, functions and common blocks
+ # i.e
+ # SUBROUTINE <thing> <rubbish>
+ # <rubbish> FUNCTION <thing> <rubbish>
+ # COMMON /<thing>/ <rubbish>
+ # /^(\s*\S+\s+FUNCTION\s+)([A-Za-z0-9_]+)(\s*\()/ ||
+
+ while (/^(\s*SUBROUTINE\s+)([A-Za-z0-9_]+)(\s*\()/ ||
+ /^(\s*[A-Za-z0-9\*]+\s+FUNCTION\s+)([A-Za-z0-9_]+)(\s*\()/ ||
+ /^(\s*COMMON\s*)([A-Za-z0-9_]+)(\s*\/)/ ) {
+
+ local($before) = $1;
+ local($interesting_thing) = $2; # see hacks below
+ local($after) = $3;
+
+# print STDERR "defs=>$before::$interesting_thing::$after::\n";
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_defd[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_defd[$s] .= "$really_interesting_thing\001";
+ } else {
+ $defs_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ $before =~ s/\s+/\\s\+/g;
+ $before =~ s/\*/\\*/g;
+ $after =~ s/\s+/\\s\+/g;
+ $after =~ s/\(/\\\(/;
+ $after =~ s/\)/\\\)/;
+
+ s/$before$interesting_thing$after//g;
+# print STDERR "repl=>$before::$interesting_thing::$after::\n";
+ }
+ # uses are the same sorts of things
+ # CALL <thing>
+ # EXTERNAL <thing>
+ while (/^(\s*CALL\s*)([A-Za-z0-9_]+)(\s*)/ ||
+ /^(\s*EXTERNAL\s*)([A-Za-z0-9_]+)(\s*)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # more hacks below
+ local($after) = $3;
+
+# print STDERR "uses=>$before::$interesting_thing::$after::\n";
+
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_used[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_used[$s] .= "$really_interesting_thing\001";
+ } else {
+ $uses_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ $before =~ s/\s+/\\s\+/g;
+ $after =~ s/\s+/\\s\+/g;
+ $after =~ s/\(/\\\(/;
+ $after =~ s/\)/\\\)/;
+
+ s/$before$interesting_thing$after//g;
+ }
+ $* = 0;
+
+ ($defs_to_return, $uses_to_return);
+}
+
+sub setup_fortran_keywords {
+ $IGNORE_WD{'REAL*8'} = 1;
+ $IGNORE_WD{'REAL'} = 1;
+ $IGNORE_WD{'CHARACTER'} = 1;
+ $IGNORE_WD{'LOGICAL'} = 1;
+ $IGNORE_WD{'COMPLEX'} = 1;
+ $IGNORE_WD{'DOUBLE'} = 1;
+ $IGNORE_WD{'INTEGER'} = 1;
+ $IGNORE_WD{'FLOAT'} = 1;
+ $IGNORE_WD{'PROGRAM'} = 1;
+ $IGNORE_WD{'COMMON'} = 1;
+ $IGNORE_WD{'SUBROUTINE'} = 1;
+ $IGNORE_WD{'FUNCTION'} = 1;
+ $IGNORE_WD{'CONTINUE'} = 1;
+ $IGNORE_WD{'WHILE'} = 1;
+ $IGNORE_WD{'IF'} = 1;
+ $IGNORE_WD{'ENDIF'} = 1;
+ $IGNORE_WD{'THEN'} = 1;
+ $IGNORE_WD{'ELSE'} = 1;
+ $IGNORE_WD{'DO'} = 1;
+ $IGNORE_WD{'END'} = 1;
+ $IGNORE_WD{'DATA'} = 1;
+ $IGNORE_WD{'PARAMETER'} = 1;
+ $IGNORE_WD{'EXTERNAL'} = 1;
+ $IGNORE_WD{'RETURN'} = 1;
+ $IGNORE_WD{'FORMAT'} = 1;
+ $IGNORE_WD{'STOP'} = 1;
+ $IGNORE_WD{'CALL'} = 1;
+ $IGNORE_WD{'READ'} = 1;
+ $IGNORE_WD{'WRITE'} = 1;
+ $IGNORE_WD{'PRINT'} = 1;
+ $IGNORE_WD{'IOSTAT'} = 1;
+ $IGNORE_WD{'FILE'} = 1;
+ $IGNORE_WD{'STATUS'} = 1;
+ $IGNORE_WD{'ABS'} = 1;
+ $IGNORE_WD{'COS'} = 1;
+ $IGNORE_WD{'SQRT'} = 1;
+ $IGNORE_WD{'SQR'} = 1;
+ $IGNORE_WD{'SIN'} = 1;
+ $IGNORE_WD{'CMPLX'} = 1;
+ $IGNORE_WD{'CONJG'} = 1;
+ $IGNORE_WD{'IMAG'} = 1;
+ $IGNORE_WD{'DBLE'} = 1;
+ $IGNORE_WD{'INT'} = 1;
+ $IGNORE_WD{'EXP'} = 1;
+ $IGNORE_WD{'LOG'} = 1;
+ $IGNORE_WD{'LT'} = 1;
+ $IGNORE_WD{'LE'} = 1;
+ $IGNORE_WD{'EQ'} = 1;
+ $IGNORE_WD{'NE'} = 1;
+ $IGNORE_WD{'GE'} = 1;
+ $IGNORE_WD{'GT'} = 1;
+ $IGNORE_WD{'NOT'} = 1;
+ $IGNORE_WD{'AND'} = 1;
+ $IGNORE_WD{'OR'} = 1;
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-hs.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-hs.lprl
new file mode 100644
index 0000000000..bef1d9a4ab
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-hs.lprl
@@ -0,0 +1,304 @@
+\section[lit2doc_for_hs]{Document-processing code for language \tr{hs}}
+
+\begin{code}
+sub rm_embedded_stuff { # return clean code + index entries (\002 separated)
+ local($_) = @_;
+ local($entries) = '';
+
+ $* = 1;
+ while (/^\s*--idx::(.*)$/) {
+ $entries .= "$1\002";
+ s/^\s*--idx::(.*)$//;
+ }
+
+ s/^\s*--\s*hide::.*$//g; # hidden comments
+
+ $* = 0;
+
+ chop($entries) if $entries ne '';
+
+ ($_, $entries);
+}
+
+sub add_code_interests {
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($defs_to_return) = '';
+
+ &setup_haskell_keywords();
+
+ $* = 1; # multi-line searches
+ s/^>//g; # de-Bird-ize
+ s/--.*$//g; # de-commentize (simple ones only)
+ s/^\s*#.*\n//g; # de-CPPize
+ s/\"[^\"\n]*\"//g; # de-stringize
+ s/\'[^\'\n]+\'//g; # de-characterize
+
+ # OK, the "interesting" DEFS are easy:
+ # functions with type sigs
+ # module definitions
+ # data <thing> =
+ # data ... = <thing> (NB: hack required)
+ # | <constructor>
+ # type <thing>
+ #
+ # CAN YOU SAY "HEURISTIC"???
+
+ while (/^(\s*)([A-Za-z0-9_']+)(\s*::)/ ||
+ /^(\s*module\s+)([A-Za-z0-9_']+)(\s*)/ ||
+ /^\s*data(\s*)([A-Z][A-Za-z0-9_']+)(\s*)=/ ||
+ /^(\s*data\s*=\s*)([A-Z][A-Za-z0-9_']+)(\s*)/ ||
+ /^(\s*type\s*)([A-Z][A-Za-z0-9_']+)(\s*=)/ ||
+ /^(\s*\|\s*)([A-Z][A-Za-z0-9_']+)(\s*)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2;
+ local($after) = $3;
+ $before =~ s/\|/\\\|/g; # oh dear
+
+#print STDERR "$before::$interesting_thing::$after:::$_\n";
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_defd[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_defd[$s] .= "$really_interesting_thing\001";
+ } else {
+ $defs_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ s/$before$interesting_thing$after//;
+ }
+ $* = 0;
+
+ ($defs_to_return, &std_codething_uses_check($s, $b, $_));
+}
+
+sub setup_haskell_keywords {
+ $IGNORE_WD{'AppendChan'} = 1;
+ $IGNORE_WD{'Array'} = 1;
+ $IGNORE_WD{'Assoc'} = 1;
+ $IGNORE_WD{'Bin'} = 1;
+ $IGNORE_WD{'Binary'} = 1;
+ $IGNORE_WD{'Bool'} = 1;
+ $IGNORE_WD{'Char'} = 1;
+ $IGNORE_WD{'Complex'} = 1;
+ $IGNORE_WD{'Double'} = 1;
+ $IGNORE_WD{'Enum'} = 1;
+ $IGNORE_WD{'Eq'} = 1;
+ $IGNORE_WD{'False'} = 1;
+ $IGNORE_WD{'Float'} = 1;
+ $IGNORE_WD{'Fractional'} = 1;
+ $IGNORE_WD{'Int'} = 1;
+ $IGNORE_WD{'Integer'} = 1;
+ $IGNORE_WD{'Ix'} = 1;
+ $IGNORE_WD{'Num'} = 1;
+ $IGNORE_WD{'Ord'} = 1;
+ $IGNORE_WD{'Ratio'} = 1;
+ $IGNORE_WD{'Rational'} = 1;
+ $IGNORE_WD{'ReadS'} = 1;
+ $IGNORE_WD{'Real'} = 1;
+ $IGNORE_WD{'RealFloat'} = 1;
+ $IGNORE_WD{'RealFrac'} = 1;
+ $IGNORE_WD{'ShowS'} = 1;
+ $IGNORE_WD{'String'} = 1;
+ $IGNORE_WD{'Text'} = 1;
+ $IGNORE_WD{'Text'} = 1;
+ $IGNORE_WD{'True'} = 1;
+ $IGNORE_WD{'abs'} = 1;
+ $IGNORE_WD{'accum'} = 1;
+ $IGNORE_WD{'accumArray'} = 1;
+ $IGNORE_WD{'acos'} = 1;
+ $IGNORE_WD{'acosh'} = 1;
+ $IGNORE_WD{'amap'} = 1;
+ $IGNORE_WD{'and'} = 1;
+ $IGNORE_WD{'approxRational'} = 1;
+ $IGNORE_WD{'approximants'} = 1;
+ $IGNORE_WD{'array'} = 1;
+ $IGNORE_WD{'asTypeOf'} = 1;
+ $IGNORE_WD{'asin'} = 1;
+ $IGNORE_WD{'asinh'} = 1;
+ $IGNORE_WD{'assocs'} = 1;
+ $IGNORE_WD{'atan'} = 1;
+ $IGNORE_WD{'atan2'} = 1;
+ $IGNORE_WD{'atanh'} = 1;
+ $IGNORE_WD{'bounds'} = 1;
+ $IGNORE_WD{'break'} = 1;
+ $IGNORE_WD{'case'} = 1;
+ $IGNORE_WD{'ceiling'} = 1;
+ $IGNORE_WD{'chr'} = 1;
+ $IGNORE_WD{'cis'} = 1;
+ $IGNORE_WD{'class'} = 1;
+ $IGNORE_WD{'concat'} = 1;
+ $IGNORE_WD{'conjugate'} = 1;
+ $IGNORE_WD{'cos'} = 1;
+ $IGNORE_WD{'cosh'} = 1;
+ $IGNORE_WD{'cycle'} = 1;
+ $IGNORE_WD{'data'} = 1;
+ $IGNORE_WD{'decodeFloat'} = 1;
+ $IGNORE_WD{'default'} = 1;
+ $IGNORE_WD{'denominator'} = 1;
+ $IGNORE_WD{'deriving'} = 1;
+ $IGNORE_WD{'div'} = 1;
+ $IGNORE_WD{'divRem'} = 1;
+ $IGNORE_WD{'drop'} = 1;
+ $IGNORE_WD{'dropWhile'} = 1;
+ $IGNORE_WD{'elems'} = 1;
+ $IGNORE_WD{'else'} = 1;
+ $IGNORE_WD{'encodeFloat'} = 1;
+ $IGNORE_WD{'enumFrom'} = 1;
+ $IGNORE_WD{'enumFromThen'} = 1;
+ $IGNORE_WD{'enumFromThenTo'} = 1;
+ $IGNORE_WD{'enumFromTo'} = 1;
+ $IGNORE_WD{'error'} = 1;
+ $IGNORE_WD{'even'} = 1;
+ $IGNORE_WD{'exp'} = 1;
+ $IGNORE_WD{'exponent'} = 1;
+ $IGNORE_WD{'filter'} = 1;
+ $IGNORE_WD{'floatDigits'} = 1;
+ $IGNORE_WD{'floatRadix'} = 1;
+ $IGNORE_WD{'floatRange'} = 1;
+ $IGNORE_WD{'floor'} = 1;
+ $IGNORE_WD{'foldl'} = 1;
+ $IGNORE_WD{'foldl1'} = 1;
+ $IGNORE_WD{'foldr'} = 1;
+ $IGNORE_WD{'foldr1'} = 1;
+ $IGNORE_WD{'fromInteger'} = 1;
+ $IGNORE_WD{'fromIntegral'} = 1;
+ $IGNORE_WD{'fromRational'} = 1;
+ $IGNORE_WD{'fromRealFrac'} = 1;
+ $IGNORE_WD{'fst'} = 1;
+ $IGNORE_WD{'gcd'} = 1;
+ $IGNORE_WD{'head'} = 1;
+ $IGNORE_WD{'hiding'} = 1;
+ $IGNORE_WD{'if'} = 1;
+ $IGNORE_WD{'imagPart'} = 1;
+ $IGNORE_WD{'import'} = 1;
+ $IGNORE_WD{'in'} = 1;
+ $IGNORE_WD{'inRange'} = 1;
+ $IGNORE_WD{'index'} = 1;
+ $IGNORE_WD{'indices'} = 1;
+ $IGNORE_WD{'infix'} = 1;
+ $IGNORE_WD{'infixl'} = 1;
+ $IGNORE_WD{'infixr'} = 1;
+ $IGNORE_WD{'init'} = 1;
+ $IGNORE_WD{'instance'} = 1;
+ $IGNORE_WD{'interface'} = 1;
+ $IGNORE_WD{'isAlpha'} = 1;
+ $IGNORE_WD{'isAlphanum'} = 1;
+ $IGNORE_WD{'isAscii'} = 1;
+ $IGNORE_WD{'isControl'} = 1;
+ $IGNORE_WD{'isDigit'} = 1;
+ $IGNORE_WD{'isLower'} = 1;
+ $IGNORE_WD{'isNullBin'} = 1;
+ $IGNORE_WD{'isPrint'} = 1;
+ $IGNORE_WD{'isSpace'} = 1;
+ $IGNORE_WD{'isUpper'} = 1;
+ $IGNORE_WD{'iterate'} = 1;
+ $IGNORE_WD{'ixmap'} = 1;
+ $IGNORE_WD{'last'} = 1;
+ $IGNORE_WD{'lcm'} = 1;
+ $IGNORE_WD{'length'} = 1;
+ $IGNORE_WD{'lex'} = 1;
+ $IGNORE_WD{'lines'} = 1;
+ $IGNORE_WD{'listArray'} = 1;
+ $IGNORE_WD{'log'} = 1;
+ $IGNORE_WD{'logBase'} = 1;
+ $IGNORE_WD{'magnitude'} = 1;
+ $IGNORE_WD{'main'} = 1;
+ $IGNORE_WD{'map'} = 1;
+ $IGNORE_WD{'max'} = 1;
+ $IGNORE_WD{'maximum'} = 1;
+ $IGNORE_WD{'min'} = 1;
+ $IGNORE_WD{'minimum'} = 1;
+ $IGNORE_WD{'mkPolar'} = 1;
+ $IGNORE_WD{'mod'} = 1;
+ $IGNORE_WD{'module'} = 1;
+ $IGNORE_WD{'negate'} = 1;
+ $IGNORE_WD{'not'} = 1;
+ $IGNORE_WD{'nub'} = 1;
+ $IGNORE_WD{'null'} = 1;
+ $IGNORE_WD{'nullBin'} = 1;
+ $IGNORE_WD{'numerator'} = 1;
+ $IGNORE_WD{'odd'} = 1;
+ $IGNORE_WD{'of'} = 1;
+ $IGNORE_WD{'or'} = 1;
+ $IGNORE_WD{'ord'} = 1;
+ $IGNORE_WD{'otherwise'} = 1;
+ $IGNORE_WD{'partialQuotients'} = 1;
+ $IGNORE_WD{'partition'} = 1;
+ $IGNORE_WD{'phase'} = 1;
+ $IGNORE_WD{'pi'} = 1;
+ $IGNORE_WD{'polar'} = 1;
+ $IGNORE_WD{'product'} = 1;
+ $IGNORE_WD{'properFraction'} = 1;
+ $IGNORE_WD{'range'} = 1;
+ $IGNORE_WD{'read'} = 1;
+ $IGNORE_WD{'readBin'} = 1;
+ $IGNORE_WD{'readList'} = 1;
+ $IGNORE_WD{'readList'} = 1;
+ $IGNORE_WD{'readParen'} = 1;
+ $IGNORE_WD{'reads'} = 1;
+ $IGNORE_WD{'readsPrec'} = 1;
+ $IGNORE_WD{'readsPrec'} = 1;
+ $IGNORE_WD{'realPart'} = 1;
+ $IGNORE_WD{'rem'} = 1;
+ $IGNORE_WD{'remove'} = 1;
+ $IGNORE_WD{'renaming'} = 1;
+ $IGNORE_WD{'repeat'} = 1;
+ $IGNORE_WD{'reverse'} = 1;
+ $IGNORE_WD{'round'} = 1;
+ $IGNORE_WD{'scaleFloat'} = 1;
+ $IGNORE_WD{'scan'} = 1;
+ $IGNORE_WD{'show'} = 1;
+ $IGNORE_WD{'showBin'} = 1;
+ $IGNORE_WD{'showChar'} = 1;
+ $IGNORE_WD{'showList'} = 1;
+ $IGNORE_WD{'showList'} = 1;
+ $IGNORE_WD{'showParen'} = 1;
+ $IGNORE_WD{'showString'} = 1;
+ $IGNORE_WD{'shows'} = 1;
+ $IGNORE_WD{'showsPrec'} = 1;
+ $IGNORE_WD{'showsPrec'} = 1;
+ $IGNORE_WD{'significand'} = 1;
+ $IGNORE_WD{'signum'} = 1;
+ $IGNORE_WD{'sin'} = 1;
+ $IGNORE_WD{'sinh'} = 1;
+ $IGNORE_WD{'snd'} = 1;
+ $IGNORE_WD{'span'} = 1;
+ $IGNORE_WD{'sqrt'} = 1;
+ $IGNORE_WD{'sum'} = 1;
+ $IGNORE_WD{'tail'} = 1;
+ $IGNORE_WD{'take'} = 1;
+ $IGNORE_WD{'takeWhile'} = 1;
+ $IGNORE_WD{'tan'} = 1;
+ $IGNORE_WD{'tanh'} = 1;
+ $IGNORE_WD{'then'} = 1;
+ $IGNORE_WD{'to'} = 1;
+ $IGNORE_WD{'toInteger'} = 1;
+ $IGNORE_WD{'toLower'} = 1;
+ $IGNORE_WD{'toRational'} = 1;
+ $IGNORE_WD{'toUpper'} = 1;
+ $IGNORE_WD{'truncate'} = 1;
+ $IGNORE_WD{'type'} = 1;
+ $IGNORE_WD{'unlines'} = 1;
+ $IGNORE_WD{'until'} = 1;
+ $IGNORE_WD{'unwords'} = 1;
+ $IGNORE_WD{'where'} = 1;
+ $IGNORE_WD{'words'} = 1;
+ $IGNORE_WD{'zip'} = 1;
+ $IGNORE_WD{'zip3'} = 1;
+ $IGNORE_WD{'zip4'} = 1;
+ $IGNORE_WD{'zip5'} = 1;
+ $IGNORE_WD{'zip6'} = 1;
+ $IGNORE_WD{'zip7'} = 1;
+ $IGNORE_WD{'zipWith'} = 1;
+ $IGNORE_WD{'zipWith3'} = 1;
+ $IGNORE_WD{'zipWith4'} = 1;
+ $IGNORE_WD{'zipWith5'} = 1;
+ $IGNORE_WD{'zipWith6'} = 1;
+ $IGNORE_WD{'zipWith7'} = 1;
+# $IGNORE_WD{''} = 1;
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-jm.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-jm.lprl
new file mode 100644
index 0000000000..cddd5f2ab4
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-jm.lprl
@@ -0,0 +1,64 @@
+\section[lit2doc_for_jm]{Document-processing code for language \tr{jm}}
+
+\begin{code}
+sub rm_embedded_stuff { # return clean code + index entries (\002 separated)
+ local($codetxt) = @_;
+
+ ($codetxt, '');
+}
+
+sub add_code_interests { # DO NOTHING
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($defs_to_return) = '';
+ local($uses_to_return) = '';
+
+# & setup_MkWorld_keywords();
+
+ $* = 1; # multi-line searches
+ s/^>//g; # de-Bird-ize
+ s/\/\*[^\/]*\*\///g;# de-commentize (necessarily fraught with peril)
+ s/\"[^\"\n]*\"//g; # de-string-ize and de-char-ize
+ s/\'[^\'\n]*\'//g;
+
+ # OK, the "interesting" DEFS are #define'd things & defns of "make" vars
+ # The latter must begin in col 1!
+
+ while (/^(\s*#define\s+)([A-Za-z_][A-Za-z0-9_]{2,})(\s*)/ ||
+ /^(\s*)([A-Za-z_][A-Za-z0-9_]{2,})(\s*=)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # see hacks below
+ local($after) = $3;
+
+#print STDERR "defs=>$before::$interesting_thing::$after::\n";
+
+ if ($interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_defd[$b] .= "$interesting_thing\001";
+ $Sec_codethings_defd[$s] .= "$interesting_thing\001";
+ } else {
+ $defs_to_return .= "$interesting_thing\001";
+ }
+ }
+ # escaping all magic chars in before/interesting/after
+ # is v important for avoiding infinite loops! (also below)
+ $before =~ s/\s+/\\s\+/g;
+ $after =~ s/\s+/\\s\+/g;
+
+ s/$before$interesting_thing$after//g;
+ }
+
+ # I AM NOT INTERESTED IN USES AT THE MOMENT
+
+ $* = 0;
+# ('', &std_codething_uses_check($s, $b, $incode));
+ ($defs_to_return, $uses_to_return);
+}
+
+#sub setup_MkWorld_keywords {
+# $IGNORE_WD{''} = 1;
+#}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-lex.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-lex.lprl
new file mode 100644
index 0000000000..7b6c8246bb
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-lex.lprl
@@ -0,0 +1,27 @@
+\section[lit2doc_for_lex]{Document-processing code for language \tr{lex}}
+
+\begin{code}
+sub rm_embedded_stuff { # return clean code + entries (\002 separated)
+ local($codetxt) = @_;
+
+ ($codetxt, '');
+}
+
+sub add_code_interests { # DO NOTHING
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+
+ # nothing special on uses; here's the lex IGNORE_WD table:
+ & setup_lex_keywords();
+
+ ('', &std_codething_uses_check($s, $b, $_));
+}
+
+sub setup_lex_keywords {
+ $IGNORE_WD{'while'} = 1;
+# $IGNORE_WD{''} = 1;
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-none.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-none.lprl
new file mode 100644
index 0000000000..c68e9a368c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-none.lprl
@@ -0,0 +1,21 @@
+\section[lit2doc_for_none]{Document-processing code for language \tr{none}}
+
+\begin{code}
+# "none" is a really nice language
+
+sub rm_embedded_stuff { # return clean code + entries (\002 separated)
+ local($codetxt) = @_;
+
+ ($codetxt, '');
+}
+
+sub add_code_interests {
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $in_code) = @_;
+
+ ('', ''); # DO NOTHING
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc-prl.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc-prl.lprl
new file mode 100644
index 0000000000..298bdb375e
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc-prl.lprl
@@ -0,0 +1,111 @@
+\section[lit2doc_for_prl]{Document-processing code for language \tr{prl}}
+
+\begin{code}
+sub rm_embedded_stuff { # return clean code + entries (\002 separated)
+ local($_) = @_;
+ local($entries) = '';
+
+ $* = 1;
+ while (/^\s*#idx::(.*)$/) {
+ $entries .= "$1\002";
+ s/^\s*#idx::(.*)$//;
+ }
+
+ s/^\s*#hide::.*$//g; # hidden comments
+
+ $* = 0;
+
+ chop($entries) if $entries ne '';
+
+ ($_, $entries);
+}
+
+sub add_code_interests { # DO NOTHING
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($defs_to_return) = '';
+ local($uses_to_return) = '';
+
+ &setup_perl_keywords();
+
+ $* = 1; # multi-line searches
+ s/^>//g; # de-Bird-ize
+ s/^#.*$//g; # de-commentize
+ s/([^\\\n])#.*$/\1/g;
+ s/\"[^\"\n]*\"//g; # de-stringize
+ s/\'[^\'\n]*\'//g;
+ s/s?\/.*\/.*\/g?//g;# de-regexp
+
+ # OK, the "interesting" DEFS are subroutines and globals
+ # sub <thing>
+ # [@$%]<thing> (=|.=)
+
+ while (/^(\s*sub\s+)([A-Za-z0-9_]+)(\s*\{)/ ||
+ /^(\s*)([\@\$\%][A-Z][A-Za-z0-9_]+)(\s*=|\s*\.=)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # see hacks below
+ local($after) = $3;
+
+#print STDERR "defs=>$before::$interesting_thing::$after::\n";
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_defd[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_defd[$s] .= "$really_interesting_thing\001";
+ } else {
+ $defs_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ # escaping all magic chars in before/interesting/after
+ # is v important for avoiding infinite loops! (also below)
+ $before =~ s/\s+/\\s\+/g;
+ $interesting_thing =~ s/\$/\\\$/;
+ $interesting_thing =~ s/\@/\\\@/;
+ $interesting_thing =~ s/\%/\\\%/;
+ $after =~ s/\s+/\\s\+/g;
+ $after =~ s/\{/\\\{/;
+ $after =~ s/\./\\\./;
+
+ s/$before$interesting_thing$after//g;
+ }
+
+ # uses are the same sorts of things
+ while (/(\&\s*)([A-Za-z0-9_]+)(\s*)/ || # subroutine calls
+ /(\s*)([\@\$\%][A-Z][A-Za-z0-9_]+)(\s*)/) {
+ local($before) = $1;
+ local($interesting_thing) = $2; # more hacks below
+ local($after) = $3;
+
+#print STDERR "uses=>$before::$interesting_thing::$after::\n";
+
+ local($really_interesting_thing) = (defined($IGNORE_WD{$interesting_thing})) ? '' : $interesting_thing;
+ if ($really_interesting_thing) {
+ if ($s != -1) {
+ $Blk_codethings_used[$b] .= "$really_interesting_thing\001";
+ $Sec_codethings_used[$s] .= "$really_interesting_thing\001";
+ } else {
+ $uses_to_return .= "$really_interesting_thing\001";
+ }
+ }
+ $before =~ s/\s+/\\s\+/g;
+ $interesting_thing =~ s/\$/\\\$/;
+ $interesting_thing =~ s/\@/\\\@/;
+ $interesting_thing =~ s/\%/\\\%/;
+ $after =~ s/\s+/\\s\+/g;
+
+ s/$before$interesting_thing$after//g;
+ }
+ $* = 0;
+
+ ($defs_to_return, $uses_to_return);
+}
+
+sub setup_perl_keywords {
+ $IGNORE_WD{'ARGV'} = 1;
+ $IGNORE_WD{'SIG'} = 1;
+ $IGNORE_WD{'ENV'} = 1;
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2doc.lprl b/web/glasgow/lit2x-0.16/literate/lit-2doc.lprl
new file mode 100644
index 0000000000..1a57fecdc9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2doc.lprl
@@ -0,0 +1,369 @@
+\section[lit2doc_code]{Code for processing documents (\tr{lit2texi} and \tr{lit2latex})}
+
+\subsection[Do_substitutions]{Doing \tr{\defines}s}
+
+Make a little \tr{perl} script from the collected substitution info
+then throw each text block at it with @eval@. We love \tr{perl}!
+
+\begin{code}
+sub do_text_substitutions {
+ # first, build up perl eval string
+ local($evalstring) = '';
+ local($text,$replacement);
+ while (($text, $replacement) = each %Define) {
+ $replacement =~ s/\\/\\\\/g; # hide slashes, etc; need something more general
+ $replacement =~ s/\//\\\//g;
+ $replacement =~ s/\$/\\\$/g; # all regexp meta-chars; sigh
+ $replacement =~ s/\%/\\\%/g;
+ $replacement =~ s/\@/\\\@/g;
+ $replacement =~ s/\^/\\\^/g;
+ $replacement =~ s/\(/\\\(/g;
+ $replacement =~ s/\)/\\\)/g;
+ $replacement =~ s/\{/\\\{/g;
+ $replacement =~ s/\}/\\\}/g;
+ $replacement =~ s/\./\\\./g;
+ $evalstring .= "s/\\\\$text\\{\\}/$replacement/g;"
+ . "s/\\\\$text\\\\ /$replacement /g;"
+ . "s/\\\\$text\\b/$replacement/g;";
+ }
+
+ # now cycle through section titles and non-code/non-verbatim blocks
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) { # titles...
+ local($_) = $Sec_title[$S];
+
+ eval($evalstring);
+ die "Subst eval failed: $@\neval_string=$eval_string\n" if $@;
+ $Sec_title[$S] = $_;
+ }
+
+ foreach ($B = 0; $B <= $#Blk_type; $B++) { # blocks...
+ if ($Blk_type[$B] !~ /(code|verb)$/) {
+ local($_) = $Blk_txt[$B];
+
+ s/\%de[a-z][a-z]\%([^\n])/\1/g;
+
+ eval($evalstring);
+ die "Subst eval failed: $@\neval_string=$eval_string\n" if $@;
+ $Blk_txt[$B] = $_;
+ }
+ }
+}
+\end{code}
+
+\subsection[Finding_codethings]{Finding interesting codethings}
+
+This code passes over the input looking for ``interesting''
+definitions and uses of things in the code (``interesting'' and
+``things'' depending on @$Code_lang@, modified by @$Lang_xref@ cues).
+It records this information in
+@Sec_codethings_defd[$S]@, @Sec_codethings_used[$S]@
+@Blk_codethings_defd[$B]@, and @Blk_codethings_used[$B]@
+(long lists of names of codethings).
+This info is used for indexing during processing and for
+cross-referencing during linking.
+
+\begin{code}
+sub find_interesting_codethings {
+
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) {
+ foreach ($B = $Sec_first_blk[$S]; $B <= $Sec_last_blk[$S]; $B++) {
+ if ($Blk_type[$B] eq 'code') {
+
+ # language-specific...
+ &add_code_interests($S, $B, $Blk_txt[$B]);
+
+ # for uses, rm duplicates
+ if ($Blk_codethings_used[$B]) {
+ $Blk_codethings_used[$B] =
+ &tidy_codething_list($Blk_codethings_used[$B]);
+ }
+ }
+ }
+ if ($Sec_codethings_used[$S]) { # tidy, as well
+ $Sec_codethings_used[$S] =
+ &tidy_codething_list($Sec_codethings_used[$S]);
+ }
+ }
+}
+
+sub std_codething_uses_check {
+
+ # section and blk to record in ($s == -1: don't update) + the code
+ local($s, $b, $_) = @_;
+ local($uses_to_return) = '';
+
+ # ANY identifier (> 2 chars) not in (presumably language-specific)
+ # IGNORE_WD table is recorded as being "used"
+ while (/([A-Za-z][A-Za-z0-9_']{2,})/) {
+ local($interesting_thing) = $1;
+ if ( ! defined($IGNORE_WD{$interesting_thing})) {
+ if ($s != -1) {
+ $Blk_codethings_used[$b] .= "$interesting_thing\001";
+ $Sec_codethings_used[$s] .= "$interesting_thing\001";
+ } else {
+ $uses_to_return .= "$interesting_thing\001";
+ }
+ }
+ s/$interesting_thing//;
+ }
+ $uses_to_return;
+}
+
+sub tidy_codething_list {
+ local($unsorted_list) = @_;
+ local(@sorted_list) = sort(split(/\001/,$unsorted_list));
+ local($prev_thing) = '';
+ local($s);
+ foreach $s (@sorted_list) {
+ if ($s eq $prev_thing) {
+ $prev_thing = $s;
+ $s = '';
+ } else {
+ $prev_thing = $s;
+ }
+ }
+ local($outlist) = join("\001",@sorted_list);
+ $outlist =~ s/\001\001+/\001/g;
+ $outlist;
+}
+\end{code}
+
+\subsection[Generating_a_document]{Generating a Texinfo or \LaTeX{} document}
+
+Code for when producing a document (either Texinfo or \LaTeX{}).
+
+\begin{code}
+sub print_intermed_document {
+
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) {
+
+ &print_section_heading($S) if $Sec_nodename[$S];
+
+ foreach ($B = $Sec_first_blk[$S]; $B <= $Sec_last_blk[$S]; $B++) {
+
+ # report where we are (lang specific)
+ print &mk_line_directive($Blk_srcfile_name[$B],$Blk_srcfile_lineno[$B]);
+
+ if ($Blk_type[$B] eq 'txt') {
+ if ($Lit2texi) {
+ local($stuff,$idxstuff) =
+ &texinfoize_text($Blk_srcfile_name[$B],
+ $Blk_srcfile_lineno[$B],
+ $Blk_txt[$B]
+ );
+ if ($stuff =~ /\n$/) {
+ print "$stuff$idxstuff";
+ } else {
+ print "$stuff\n$idxstuff";
+ }
+ } else {
+ local($stuff,$idxstuff) =
+ &latexize_text($Blk_srcfile_name[$B],
+ $Blk_srcfile_lineno[$B],
+ $Blk_txt[$B]
+ );
+ print "$stuff$idxstuff"; # never a newline in between
+ }
+
+ } elsif ($Blk_type[$B] =~ /^(code|pseudocode)$/) {
+ local($what) = $1;
+ if ($what eq 'code' && $Blk_magic[$B] ne 'main') {
+ print "CODE FOR ",(($Blk_magic[$B] =~ /,/) ? "RIBBONS" : "RIBBON");
+ print ": ",$Blk_magic[$B],"\n\n"
+ if $Lit2texi;
+ print ": \\mbox\{\\tt\{\}",&verb2latex("\\tt",$Blk_magic[$B]),"\}\n\n"
+ if $Lit2latex;
+ }
+
+ &print_code_blk($Blk_txt[$B]) if $Lit2latex; # lang specific
+ &std_print_code_blk($Blk_txt[$B]) if $Lit2texi; # _always_
+
+ &print_index_entries_for_code_blk($B)
+ if $Lang_xref !~ /noindex/;
+
+ &print_latex_labels_for_code_blk_defs($B) if $Lit2latex;
+
+# print "\\par\n" if $Lit2latex; # doubtful long-term value
+
+ } elsif ($Blk_type[$B] eq 'menu') {
+ if ($Lit2texi) { # menus only apply for Texinfo
+ print "\@menu\n";
+ print $Blk_txt[$B];
+ print "\@end menu\n";
+ }
+
+ } elsif ($Blk_type[$B] eq 'rawlatex') {
+ if ($Lit2latex) {
+ print "\001beginrawlatex\003\n";
+ print $Blk_txt[$B];
+ print "\001endrawlatex\003\n";
+ }
+
+ } elsif ($Blk_type[$B] eq 'tabular') {
+ if ($Lit2texi) {
+ local($text_stuff,$idx_stuff) = &texinfoize_table_body($Blk_txt[$B]);
+ print "\@example\n";
+ print &texinfoize_tabular($text_stuff);
+ print "\@end example\n$idx_stuff";
+ } else {
+ print "\\begin\{tabular\}",$Blk_magic[$B],"\n";
+ local($text_stuff,$idx_stuff) = &latexize_text($Blk_srcfile_name[$B],
+ $Blk_srcfile_lineno[$B],
+ $Blk_txt[$B]
+ );
+ print "$text_stuff\n\\end\{tabular\}\n$idx_stuff\n";
+ }
+ } elsif ($Blk_type[$B] =~ /verb$/) {
+ if ($Lit2texi) {
+ print "\@example\n",&texinfoize_verb($Blk_txt[$B]),"\@end example\n"
+ if $Blk_type[$B] eq 'verb';
+ print "\@format\n",&texinfoize_verb($Blk_txt[$B]),"\@end format\n"
+ if $Blk_type[$B] eq 'flushverb';
+ } else {
+#new: nothing for flushverb yet
+ print "\\begin\{verbtext\}";
+ local($mangled_verb) = &verb2verbcode($Blk_txt[$B]);
+ if (($mangled_verb =~ s/\n/\n/g) >= 5) { # a terrible way to count lines
+ print "\\codeallowbreaks\{\}";
+ }
+ print "\n";
+ $mangled_verb =~ s/\n$//; # don't want newline before \end{verbtext}
+ print $mangled_verb;
+ print "\\end\{verbtext\}%\n";
+#old:
+# print "\\BeginLitVerb\n"
+# if $Blk_type[$B] eq 'verb';
+# print "\\BeginLitVerbNoIndent\n"
+# if $Blk_type[$B] eq 'flushverb';
+# local($mangled_verb) = "\\mbox\{\\tt\{\}" .
+# &verb2latex("\\tt",$Blk_txt[$B]) .
+# "\}";
+# # chop junk off the end (nobody said life was easy)
+# $mangled_verb =~ s/\\\\\n\\mbox\{\\tt\{\}\}$//;
+# print $mangled_verb;
+# print "\\EndLitVerb\n";
+# print "\\par\n";
+ }
+ } elsif ($Blk_type ne '') { # let null ones through (?)
+ &not_OK($Blk_srcfile_name[$B], $Blk_srcfile_lineno[$B],
+ "unknown or unimplemented blk type: $Blk_type[$B]\n");
+ }
+ }
+ # end of section stuff would go here, e.g., where
+ # ref'd ribbons can be found (?)
+ }
+}
+\end{code}
+
+\subsection[Other_doc_only_code]{Other code for document generation}
+
+\begin{code}
+sub print_section_heading { # dump the collected info for this section
+ local($s) = @_;
+
+ # fix up section/node's owner if necessary (recorded in first blk, I hope...)
+ if ($Show_node_owner && ! $Sec_owner[$s]) {
+ local($srcfile) = $Blk_srcfile_name[$Sec_first_blk[$s]];
+ if (! defined($srcfile) || ! -f $srcfile) {
+ &not_OK("","","can't find source file: $srcfile\n");
+ } else {
+ local(@srcfile_stats) = stat($srcfile);
+ local(@owner_stuff) = getpwuid($srcfile_stats[4]);
+
+ $Sec_owner[$s] = $owner_stuff[0];
+ }
+ }
+
+ chop($Sec_aliases[$S]) if $Sec_aliases[$S];
+
+ local($guessname,$guessline) = ('',-1);
+ # try to guess where \section command is
+ if (($Sec_first_blk[$S] >= $Sec_last_blk[$S])
+ && (! &empty_blk_p($Sec_first_blk[$S]) )) {
+ $guessname = $Blk_srcfile_name[$Sec_first_blk[$S]];
+ $guessline = ($Blk_srcfile_lineno[$Sec_first_blk[$S]] - 1);
+ }
+ print "\001section\003",$Sec_depth[$s],
+ "\002",$Sec_nodename[$s],
+ "\002",$Sec_nodespec[$s],
+# I doubt that texinfoize_text call... (idx_stuff?)
+ "\002",(($Lit2texi) ? &texinfoize_text('???','???',$Sec_owner[$s])
+ : $Sec_owner[$s]),
+ "\002",&de_newlined($Sec_extra_menu_entries[$s]),
+ "\002",$Sec_codethings_defd[$S],
+ "\002",$Sec_aliases[$S],
+ "\002",$Sec_codethings_used[$S],
+ "\002",$guessname,
+ "#%%#",$guessline,
+ "#%%#";
+
+ local($fixed_title) = $Sec_title[$s];
+ if ($Lit2latex) {
+ local($title,$idx_stuff) = &latexize_text("???","???",$fixed_title);
+ print "{$title}";
+ # no label if funny chars found inside !!!
+ # (perhaps a warning?)
+ print "\\label{",$Sec_nodename[$s],"}" if $Sec_nodename[$s] !~ /[\\\{\}\$\%]/;
+ print "\n$idx_stuff";
+
+ } else { # $Lit2texi
+ local($title,$idxtitle) = &texinfoize_text('???','???',$fixed_title);
+ print " $title\n$idxtitle";
+ }
+}
+
+sub print_index_entries_for_code_blk {
+ # see also print_latex_labels_for_code_blk_defs
+ local($b) = @_;
+
+ # print an index entry for each definition in this code blk
+ local($d);
+ foreach $d (split(/\001/, $Blk_codethings_defd[$b])) {
+ if ($d && $Lit2texi) {
+ print "\@cindex ".&mk_texi_index_entry("$d [def]")."\n";
+ } elsif ($d) {
+ # thinking about a "\|ttunderline" in there, too...
+ print "\\index\{".&mk_latex_index_entry('tt',$d)."\|underline\}\%\n";
+ }
+ }
+
+ # print the uses that want indexing
+ # this cannot be done until linking time
+ print "\001index_uses\003",$Blk_codethings_used[$b],"\n"
+ if $Blk_codethings_used[$b];
+
+ # we want this for xrefs too -- but only those not def'd here
+ if ($Lit2latex && $Blk_codethings_used[$b]) {
+ local(@far_use) = split(/\001/,$Blk_codethings_used[$b]);
+ local($f);
+
+ foreach $f (@far_use) { # a good enough check ?
+ if ( ($Blk_codethings_defd[$b] =~ /^$f/)
+ || ($Blk_codethings_defd[$b] =~ /$f$/)
+ || ($Blk_codethings_defd[$b] =~ /\001$f\001/)) {
+ $f = '';
+ }
+ }
+ $f = join("\001join\003",@far_use); # join & tidy up
+ $f =~ s/(\001join\003){2,}/\001join\003/g;
+ $f =~ s/^\001join\003//;
+ $f =~ s/\001join\003$//;
+ $f =~ s/\001join\003/\001/g;
+
+ print "\001xref_uses\003$f\n" if $f;
+ }
+}
+
+sub fiddle_sectiontypes {
+ local($_) = @_;
+
+ # \[Ss]ectiontype; rm shorthand first
+ s/\\([Ss])ectionref\{([^\}]+)\}/\\\1ectiontype\{\2\}~\\ref\{\2\}/g;
+
+ # nothing else can be done until linking
+ $_;
+}
+
+# a trailing 1 seems to be the habit for inc'd perl files
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-c.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-c.lprl
new file mode 100644
index 0000000000..c50cbeed7f
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-c.lprl
@@ -0,0 +1,22 @@
+\section[lit2latex_for_c]{Lit2latex-only code for language \tr{c}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ &std_tgrind_code_blk('c', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-f.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-f.lprl
new file mode 100644
index 0000000000..955f9cf5c6
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-f.lprl
@@ -0,0 +1,22 @@
+\section[lit2latex_for_f]{Lit2latex-only code for language \tr{Fortran}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ &std_tgrind_code_blk('f', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-hs.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-hs.lprl
new file mode 100644
index 0000000000..01781123c2
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-hs.lprl
@@ -0,0 +1,22 @@
+\section[lit2latex_for_hs]{Lit2latex-only code for language \tr{hs}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ &std_tgrind_code_blk('hs', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-jm.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-jm.lprl
new file mode 100644
index 0000000000..ae544db187
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-jm.lprl
@@ -0,0 +1,22 @@
+\section[lit2latex_for_jm]{Lit2latex-only code for language \tr{jm} (``make-world'' files)}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ &std_tgrind_code_blk('c', $codetxt); # pretend it's C
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-lex.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-lex.lprl
new file mode 100644
index 0000000000..a0f17f6c33
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-lex.lprl
@@ -0,0 +1,23 @@
+\section[lit2latex_for_lex]{Lit2latex-only code for language \tr{lex}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ # 'yacc' is the nearest thing
+ &std_tgrind_code_blk('yacc', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-none.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-none.lprl
new file mode 100644
index 0000000000..582265632c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-none.lprl
@@ -0,0 +1,23 @@
+\section[lit2latex_for_none]{Lit2latex-only code for language \tr{none}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ # 'src' is the generic tgrind thing
+ &std_tgrind_code_blk('src', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex-prl.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex-prl.lprl
new file mode 100644
index 0000000000..d1850cefd0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex-prl.lprl
@@ -0,0 +1,22 @@
+\section[lit2latex_for_prl]{Lit2latex-only code for language \tr{prl}}
+
+\begin{code}
+sub print_code_blk { # just use the std
+ local($codetxt) = @_;
+
+ if ($Lang_typeset =~ /tgrind/) {
+ &std_tgrind_code_blk('perl', $codetxt);
+ } else {
+ &std_print_code_blk($codetxt);
+ }
+}
+
+sub mk_code_frag {
+ local($codetxt) = @_;
+
+ &std_mk_code_frag($codetxt);
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2latex.lprl b/web/glasgow/lit2x-0.16/literate/lit-2latex.lprl
new file mode 100644
index 0000000000..9d45a1e3c8
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2latex.lprl
@@ -0,0 +1,329 @@
+\section[lit2latex_only]{Code for generating \LaTeX{} files}
+
+\begin{code}
+# I'm putting these two routines first,
+# I think because perl has a bug in it
+sub add_latex_literals {
+ local($_) = @_;
+
+ s/\001lateXLitbackslash\003/\{\\char'134\}/g;
+ s/\001lateXLitlbrace\003/\{\\char'173\}/g;
+ s/\001lateXLitrbrace\003/\{\\char'175\}/g;
+ s/\001lateXLithash\003/\{\\char'43\}/g;
+
+ $_;
+}
+
+sub verb2latex { # takes a blob of text and produces a bunch of \mbox{$font...}'s
+ # if you ensure no newlines, then no \\mbox stuff will come out
+ # assumes \tt really; if you're doing something else, you may have to
+ # fiddle; see verb2rm, for example.
+ local($font, $_) = @_;
+
+ study($_);
+
+ s/\\/\001lateXLitbackslash\003/g;
+ s/\{/\001lateXLitlbrace\003/g;
+ s/\}/\001lateXLitrbrace\003/g;
+
+ s/\n/\}\\\\\n\\mbox\{$font\{\}/g;
+
+ s/\#/\\\#/g;
+ s/\&/\\\&/g;
+ s/ /\\ /g;
+ s/\!/\{\\char'41\}/g;
+ s/\"/\{\\char'42\}/g;
+ s/\$/\{\\char'44\}/g;
+ s/\%/\{\\char'45\}/g;
+ s/\*/\{\\char'52\}/g;
+ s/\</\{\\char'74\}/g;
+ s/\>/\{\\char'76\}/g;
+ s/\@/\{\\char'100\}/g;
+ s/\^/\{\\char'136\}/g;
+ s/\_/\{\\char'137\}/g;
+ s/\|/\{\\char'174\}/g;
+ s/\~/\{\\char'176\}/g;
+
+ &add_latex_literals($_);
+}
+
+sub verb2verbcode { # to go with Olin Shivers's (verb)code.sty
+ # need to escape: \ { }
+ local($_) = @_;
+
+ s/\\/\\\\/g;
+ s/\{/\\\{/g;
+ s/\}/\\\}/g;
+
+ $_;
+}
+
+sub verb2rm {
+ local($_) = @_;
+ $_ = &verb2latex("\\ShouldNotBeUsed", $_);
+ # now undo some of it (because ain't no such chars in CMR roman font)
+
+ s/\{\\char'74\}/\$\\langle\$/g; # <
+ s/\{\\char'76\}/\$\\rangle\$/g; # >
+ s/\{\\char'134\}/\$\\backslash\$/g; # \
+ s/\{\\char'137\}/\\_/g; # _
+ s/\{\\char'173\}/\\{/g; # {
+ s/\{\\char'174\}/\$\|\$/g; # |
+ s/\{\\char'175\}/\\}/g; # }
+ s/\{\\char'42\}/\{\\char'175\}/g; # " -- a nicer glyph
+
+ $_;
+}
+
+sub latexize_text {
+ # is given deatified text
+ # returns text and index entries
+ #
+ local($srcfilename,$srclineno,$_) = @_;
+ local($idx_real) = '';
+ local($idx_maybe) = '';
+
+ # do \MathMode, \tr, and \codeInText first because they might be
+ # inside other things
+
+ s/\\MathMode\{([^\}]*)\}/\$\1\$/g;
+
+ while (/\\(pl|tr)\{([^\}]*)\}/) {
+ local($plain_or_typing) = $1;
+ local($guts) = &deatified2verb($2);
+
+ $guts = "\\mbox\{" . &verb2rm($guts). "\}"
+ if $plain_or_typing eq 'pl';
+ $guts = "\\mbox\{\\tt\{\}" . &verb2latex("\\tt",$guts). "\}"
+ if $plain_or_typing eq 'tr';
+
+ s/\\(pl|tr)\{[^\}]*\}/$guts/;
+ }
+
+
+ while (/\\codeInText\{([^\}]*)\}/) {
+ local($raw_code) = &deatified2verb($1);
+ local($indexing) = 1;
+
+ $raw_code =~ s/\\@/@/g; # the one escaped thing
+
+ if ($raw_code =~ /\001noindex\003/) {
+ $indexing = 0;
+ $raw_code =~ s/\001noindex\003//;
+ }
+
+ local($munged_code) = &mk_code_frag($raw_code);
+
+ if ($indexing) {
+ local($cdefs, $cuses) = &add_code_interests(-1,-1,$raw_code);
+ local($c);
+ # index all defs and uses
+ foreach $c (split(/\001/, $cdefs )) {
+ if ($c) {
+ # internally known indexing command
+ $idx_real .= "\\index\{".&mk_latex_index_entry('tt',$c)."\|underline\}\%\n";
+ }
+ }
+ # uses are only indexed if the defined thing is known
+ # can't be done until link time
+ foreach $c (split(/\001/, $cuses)) {
+ if ($c) {
+ $idx_maybe .= "\001index_uses\003$c\n";
+ }
+ }
+ }
+ s/\\codeInText\{[^\}]*\}/$munged_code$index_call/;
+ }
+
+# $_ .= $idx_real if $idx_real;
+# $_ .= "\%\n$idx_maybe" if $idx_maybe;
+
+ while (/\\index\{([^\}]+)\}/) {
+ local($guts) = &deatified2verb($1);
+
+ $guts =~ s/\\@/\@/g; # de-escape them
+ $guts =~ s/\\!/\!/g;
+ $guts = &mk_latex_index_entry('rm',$guts);
+
+ s/\\index\{([^\}]+)\}/\\index!_\{$guts\}/; #temp two
+ }
+ s/\\index!_\{/\\index\{/g; # fix temp two
+
+ s/\\item\s*\n/\\item\{\}\n/g;
+
+ s/(\\begin\{comment\})/\{\\small \1/g;
+ s/(\\end\{comment\})/\1\}/g;
+
+ s/\\begin\{itemise\}/\\begin\{itemize\}/g;
+ s/\\end\{itemise\}/\\end\{itemize\}/g;
+
+ s/\\@/\@/g;
+
+ # the automagically supplied \makeindex...
+ s/(\\begin\{document\})/\\makeindex\n\1/;
+
+ # check for unknown environments (only at beginning of lines; easier)
+ # mark good ones as \begin!_/\end!_
+ # bad ones as \begin!!/\end!!
+ while (/^\\(begin|end)\{([A-Za-z]+)\}/) {
+ if ( $KNOWN_ENV{$2} ) { # good
+ s/\\(begin|end)\{([A-Za-z]+)\}/\\\1!_\{\2\}/;
+ } else { # bad
+ print STDERR "warning: unrecognised environment: $2\n";
+ s/\\(begin|end)\{([A-Za-z]+)\}/\\\1!!\{\2\}/;
+ }
+ }
+ # unmark both good and bad ones
+ # (they were presumably put in for a reason)
+ s/\\(begin|end)!_\{([A-Za-z]+)\}/\\\1\{\2\}/g;
+ s/\\(begin|end)!!\{([A-Za-z]+)\}/\\\1\{\2\}/g;
+
+ ( &deatified2verb_nl(&fiddle_sectiontypes($_)),
+ $idx_real . $idx_maybe
+ );
+}
+
+sub mk_latex_index_entry { # also used in linker
+ local($font, $raw_text) = @_;
+ local(@sub_entries) = split(/\001idxsubitem\003/, $raw_text);
+ local($sube,$sortstuff,$printstuff);
+
+ foreach $sube (@sub_entries) {
+ if ($sube =~ /(.*[^\\])\001idxsort\003(.*)/) {
+ $sortstuff = $1;
+ $printstuff = $2;
+ } else {
+ $sortstuff = $sube;
+ $printstuff = $sube;
+ }
+ $sortstuff =~ s/"/""/g;
+ $sortstuff =~ s/!/"!/g;
+ $sortstuff =~ s/\\/"\\/g;
+ $sortstuff =~ s/\{/"\{/g;
+ $sortstuff =~ s/\}/"\}/g;
+ $sortstuff =~ s/\@/"\@/g;
+ $sortstuff =~ s/\|/"\|/g;
+
+ if ($font eq 'tt') {
+ $sube = "$sortstuff\@\\protect\{\\tt\{\}" . &verb2latex("\\tt",$printstuff) . "\}";
+ } elsif ($font eq 'rm') {
+ $sube = "$sortstuff\@\\protect\{" . &verb2rm($printstuff) . "\}";
+ } else {
+ die "unknown font code: $font\n";
+ }
+ }
+
+ # stick it back together for makeindex
+ join('!',@sub_entries);
+}
+
+sub print_latex_labels_for_code_blk_defs {
+ # see also print_index_entries_for_code_blk
+ local($b) = @_;
+
+ # print a label for each definition in this code blk
+ local($d);
+ foreach $d (split(/\001/, $Blk_codethings_defd[$b])) {
+ # fiddling must match that in lit-linker
+ $d =~ s/\%/<percent>/g; # and other funny chars?
+ $d =~ s/\$/<dollar>/g;
+ $d =~ s/\\/<slash>/g;
+ print "\\label\{def::$d\}\%\n" if $d;
+ }
+ # see what is done with \001xref_uses\003 in linker
+}
+
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ ( (! $filename) ? '' : "\%\% LINE $lineno \"$filename\"\n");
+}
+
+sub std_print_code_blk { # straight verbatim for those who want it
+ local($codetxt) = @_;
+
+ # language specific
+ local($newtxt,$idx_list) = &rm_embedded_stuff($codetxt);
+
+#new
+ print "\\begin\{verbcode\}";
+ print "\\hrule\{\}" if $Lang_typeset =~ /ruled/;
+
+ local($mangled_code) = &verb2verbcode($newtxt);
+ if (($mangled_code =~ s/\n/\n/g) >= 5) { # a terrible way to count lines
+ print "\\codeallowbreaks\{\}";
+ }
+ print "\n";
+ $mangled_code =~ s/\n$//; # don't want newline before \end{verbcode}
+ print $mangled_code;
+
+ print "\n\\hrule" if $Lang_typeset =~ /ruled/;
+ print "\\end\{verbcode\}%\n";
+
+#old
+# print "\\BeginLitCodeNoIndent\n";
+# print "\\hrule\n" if $Lang_typeset =~ /ruled/;
+#
+# local($mangled_code) = "\\mbox\{\\tt\{\}" .
+# &verb2latex("\\tt",$newtxt) .
+# "\}";
+# # chop junk off the end (nobody said life was easy)
+# $mangled_code =~ s/\\\\\n\\mbox\{\\tt\{\}\}$//;
+# print $mangled_code;
+#
+# print "\\hrule\n" if $Lang_typeset =~ /ruled/;
+#
+# print "\\EndLitCode\n";
+
+ if ($Lang_xref !~ /noindex/) {
+ local($i);
+ foreach $i (split(/\002/, $idx_list )) {
+ print "\\index\{".&mk_latex_index_entry('tt',$i)."\}\%\n" if $i;
+ }
+ }
+}
+
+sub std_tgrind_code_blk { # push it through tgrind
+ local($lang, $codetxt) = @_;
+
+ # language specific
+ local($newtxt,$idx_list) = &rm_embedded_stuff($codetxt);
+
+ print "\\par\\addvspace\{0.1in\}\n";
+
+ print "\\hrule\n\\vskip .5\\baselineskip\n" if $Lang_typeset !~ /unruled/;
+
+# print "\\begin\{small\}\n\\begin\{tgrind\}\n";
+ print "\\begin\{tgrind\}\n";
+ local($mangled_code) = &filter_string("unexpand -a | $Tgrind_pgm -f -l $lang -", $newtxt);
+
+ print $mangled_code;
+ print "\\end\{tgrind\}\n";
+# print "\\end\{tgrind\}\n\\end\{small\}\n";
+
+ print "\\vskip .5\\baselineskip\n\\hrule\n" if $Lang_typeset !~ /unruled/;
+
+ print "\\addvspace\{0.1in\}\n";
+
+ if ($Lang_xref !~ /noindex/) {
+ local($i);
+ foreach $i (split(/\002/, $idx_list )) {
+ print "\\index\{".&mk_latex_index_entry('tt',$i)."\}\%\n" if $i;
+ }
+ }
+}
+
+sub std_mk_code_frag { # straight verbatim for those who want it
+ local($codetxt) = @_;
+
+ local($mangled_code) = "\\mbox\{\\tt\{\}" .
+ &verb2latex("\\tt",$codetxt) .
+ "\}";
+ # chop junk off the end (nobody said life was easy)
+ $mangled_code =~ s/\\\\\n\\mbox\{\\tt\{\}\}$//;
+ $mangled_code;
+}
+
+# a trailing 1 seems to be the habit for inc'd perl files
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-c.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-c.lprl
new file mode 100644
index 0000000000..6bfb39e8c9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-c.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_c]{Lit2pgm-only code for language \tr{c}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ "# line $lineno \"$filename\"\n";
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-f.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-f.lprl
new file mode 100644
index 0000000000..c31ced58e2
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-f.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_f]{Lit2pgm-only code for language \tr{Fortran}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ "# line $lineno \"$filename\"\n";
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-hs.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-hs.lprl
new file mode 100644
index 0000000000..dedba6f47b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-hs.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_hs]{Lit2pgm-only code for language \tr{hs}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ "\{-# LINE $lineno \"$filename\" -\}\n";
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-jm.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-jm.lprl
new file mode 100644
index 0000000000..14ccee2d95
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-jm.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_jm]{Lit2pgm-only code for language \tr{jm}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ "# line $lineno \"$filename\"\n";
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-lex.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-lex.lprl
new file mode 100644
index 0000000000..8c75337392
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-lex.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_lex]{Lit2pgm-only code for language \tr{lex}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+ # toss it
+ '';
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-none.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-none.lprl
new file mode 100644
index 0000000000..6f5e8218c7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-none.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_none]{Lit2pgm-only code for language \tr{none}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+ # toss it
+ '';
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm-prl.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm-prl.lprl
new file mode 100644
index 0000000000..a8af7020cc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm-prl.lprl
@@ -0,0 +1,12 @@
+\section[lit2pgm_for_prl]{Lit2pgm-only code for language \tr{prl}}
+
+\begin{code}
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+ # same as C
+ "# line $lineno \"$filename\"\n";
+}
+
+# so we get 'do'ne correctly
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2pgm.lprl b/web/glasgow/lit2x-0.16/literate/lit-2pgm.lprl
new file mode 100644
index 0000000000..5ce12b7a04
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2pgm.lprl
@@ -0,0 +1,53 @@
+\section[lit2pgm_only]{Code only for \tr{lit2pgm}}
+
+\begin{code}
+sub spit_out_ribbons_code {
+ local(@Ribbons_to_get) = @_;
+ local($r);
+ print STDERR "spitting code for ribbons @Ribbons_to_get\n" if $Debugging;
+
+ foreach $r (@Ribbons_to_get) {
+ local(@ribbon_blk_nos) = split(/,/,$Ribbon_blks{$r});
+ local($b);
+ foreach $b (@ribbon_blk_nos) {
+ print &mk_line_directive($Blk_srcfile_name[$b],$Blk_srcfile_lineno[$b]);
+
+ if ($Blk_txt[$b] !~ /\\insertribbon/) {
+ # safe to just go "dump"...
+ # de-Birdize the code block; urgh
+ $* = 1; # multiline matches...
+ $Blk_txt[$b] =~ s/^>//g;
+ $* = 0; # back to one-line matches...
+ print $Blk_txt[$b];
+
+ } else { # gotta look around...
+ local(@blk_txt_lns) = split(/\n/,$Blk_txt[$b]);
+ local($l, $called_ribbon);
+
+ local($i) = 0;
+ foreach $l (@blk_txt_lns) {
+ if ($l =~ /^\s*\\insertribbon\{(.*)\}\s*$/) { # must be alone on line
+ $called_ribbon = $1;
+ if (! $Ribbon_blks{$called_ribbon}) {
+ &not_OK($Blk_srcfile_name[$b],($Blk_srcfile_lineno[$b]+$i),
+ "no code found for ribbon: $called_ribbon\n");
+
+ } else { # recurse...
+ &spit_out_ribbons_code($called_ribbon);
+ }
+ } else {
+ # de-Birdize the code line...
+ $l =~ s/^>//;
+ print "$l\n";
+ }
+ $i++;
+ }
+ }
+ }
+ }
+}
+
+# a trailing 1 seems to be the habit for inc'd perl files
+1;
+\end{code}
+
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-c.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-c.lprl
new file mode 100644
index 0000000000..fcc41bb7c7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-c.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_c]{Texinfo-only code for language \tr{c}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-f.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-f.lprl
new file mode 100644
index 0000000000..e35eb33266
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-f.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_f]{Texinfo-only code for language \tr{Fortran}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-hs.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-hs.lprl
new file mode 100644
index 0000000000..1144bd5d30
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-hs.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_hs]{Texinfo-only code for language \tr{hs}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-jm.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-jm.lprl
new file mode 100644
index 0000000000..a9fa29e414
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-jm.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_jm]{Texinfo-only code for language \tr{jm}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-lex.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-lex.lprl
new file mode 100644
index 0000000000..8cf9c49bcc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-lex.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_lex]{Texinfo-only code for language \tr{lex}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-none.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-none.lprl
new file mode 100644
index 0000000000..b04a327718
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-none.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_none]{Texinfo-only code for language \tr{none}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi-prl.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi-prl.lprl
new file mode 100644
index 0000000000..f22e907ae9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi-prl.lprl
@@ -0,0 +1,6 @@
+\section[texinfo_for_prl]{Texinfo-only code for language \tr{prl}}
+
+\begin{code}
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2texi.lprl b/web/glasgow/lit2x-0.16/literate/lit-2texi.lprl
new file mode 100644
index 0000000000..d63c19c654
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2texi.lprl
@@ -0,0 +1,434 @@
+\section[lit2texi_only]{Code for generating Texinfo files}
+
+\begin{code}
+sub texinfoize_text {
+ # is given deatified text
+ # returns text and index entries
+ #
+ local($srcfilename,$srclineno,$_) = @_;
+ local($idx_real) = '';
+ local($idx_maybe) = '';
+
+ # do \MathMode, \tr, and \codeInText first because they might be
+ # inside other things
+
+ while (/\\MathMode\{([^\}]*)\}/) { # I like this easy stuff
+ local($guts) = $1;
+
+ # arrows to start with...
+ $guts =~ s/\\leftarrow/->/g;
+ $guts =~ s/\\Leftarrow/=>/g;
+ $guts =~ s/\\rightarrow/<-/g;
+ $guts =~ s/\\Rightarrow/<=/g;
+ $guts =~ s/\\leftrightarrow/<->/g;
+ $guts =~ s/\\Leftrightarrow/<=>/g;
+ $guts =~ s/\\longleftarrow/-->/g;
+ $guts =~ s/\\Longleftarrow/==>/g;
+ $guts =~ s/\\longrightarrow/<--/g;
+ $guts =~ s/\\Longrightarrow/<==/g;
+ $guts =~ s/\\longleftrightarrow/<-->/g;
+ $guts =~ s/\\Longleftrightarrow/<==>/g;
+
+ $guts =~ s/\\alpha/alpha/g;
+ $guts =~ s/\\beta/beta/g;
+
+ s/\\MathMode\{([^\}]*)\}/$guts/;
+ }
+
+ while (/\\(pl|tr)\{([^\}]*)\}/) {
+ local($plain_or_typing) = $1;
+ local($guts) = $2;
+
+ $guts =~ s/\\/\001backslash\003/g;
+ $guts =~ s/\~/\001twiddle\003/g;
+ $guts =~ s/\@/\\\@/g;
+ $guts =~ s/\001lbrace\003/\\\001lbrace\003/g;
+ $guts =~ s/\001rbrace\003/\\\001rbrace\003/g;
+ # protect the following for now ... (see below)
+ $guts =~ s/\`\`/\001tex-open-double-quotes\003/g;
+ $guts =~ s/\'\'/\001tex-close-double-quotes\003/g;
+
+ s/\\(pl|tr)\{[^\}]*\}/\\w\{$guts\}/
+ if $plain_or_typing eq 'pl';
+ s/\\(pl|tr)\{[^\}]*\}/\\w\{\\samp\{$guts\}\}/
+ if $plain_or_typing eq 'tr';
+ }
+
+ while (/\\codeInText\{([^\}]*)\}/) {
+ local($raw_code) = $1;
+ local($indexing) = 1;
+
+ $raw_code =~ s/\\\@/\@/g; # remove the one kind of escape
+
+ if ($raw_code =~ /\001noindex\003/) {
+ $indexing = 0;
+ $raw_code =~ s/\001noindex\003//;
+ }
+
+ $munged_code = $raw_code;
+ $munged_code =~ s/\\/\001backslash\003/g;
+ $munged_code =~ s/\~/\001twiddle\003/g;
+ $munged_code =~ s/\@/\\\@/g; # now put it back in
+ $munged_code =~ s/\001lbrace\003/\\\001lbrace\003/g;
+ $munged_code =~ s/\001rbrace\003/\\\001rbrace\003/g;
+
+ if ($indexing) {
+ local($cdefs, $cuses) = &add_code_interests(-1,-1,&deatified2verb($raw_code));
+ local($c);
+ # index all defs and uses
+ foreach $c (split(/\001/, $cdefs)) {
+ if ($c) {
+ $idx_real .= "\\cindex ".&mk_texi_index_entry("$c [def]")."\n";
+ }
+ }
+ # uses are only indexed if the defined thing is known
+ # can't be done until link time
+ foreach $c (split(/\001/, $cuses)) {
+ if ($c) {
+ $idx_maybe .= "\001index_uses\003$c\n";
+ }
+ }
+ }
+ # this really should use &mk_code_frag ...
+
+ s/\\codeInText\{[^\}]*\}/\\w\{\\samp\{$munged_code\}\}/;
+ }
+
+ if (/\\maketitle\n/) {
+ local($title_stuff) = '';
+ $title_stuff .= "\\center $Doc_title\n" if $Doc_title;
+ $title_stuff .= "\n\\center $Doc_author\n" if $Doc_author;
+ $title_stuff .= "\n\\center $Doc_date\n" if $Doc_date;
+ $title_stuff .= "\n" if ($Doc_title || $Doc_author || $Doc_date);
+ if ($title_stuff ne '') {
+ print STDERR "$Pgm: warning: an unfixed perl 4.035 crashes here!\n";
+ print STDERR "(a patch for perl is distributed with Glasgow Haskell)\n";
+# what happened to idx stuff ?
+ $title_stuff = &texinfoize_text($srcfilename, ($srclineno + $i), $title_stuff);
+ }
+ s/\\maketitle\n/$title_stuff/;
+ }
+
+ while (/\\heading\{([^\}]+)\}\n/) {
+ local($title) = &deatified2verb($1);
+ s/\\heading\{([^\}]+)\}\n/\\heading $title\n/;
+ }
+
+ while (/\\index\{([^\}]+)\}/) {
+ local($guts) = &deatified2verb($1);
+
+ $guts =~ s/\\@/\@/g; # de-escape them
+ $guts =~ s/\\!/\!/g;
+ $guts = &mk_texi_index_entry($guts);
+
+ $idx_real .= "\\cindex " . $guts . "\n";
+ s/\\index\{([^\}]+)\}//;
+ }
+
+ s/\\item\s+([^\[\n])/\\item\n\1/g; # must be first for \item
+
+ # the following will get messed up if you do:
+ # \item [ ......... ] .......]
+
+ while (/\\item\s*\[(.+)\]\s*\n/) {
+ local($item_tag) = &deatified2verb($1);
+ s/\\item\s*\[(.+)\]\s*\n/\\item $item_tag\n/;
+ }
+ while (/\\item\s*\[(.+)\]\s*(\S)/) {
+ local($item_tag) = &deatified2verb($1);
+ s/\\item\s*\[(.+)\]\s*(\S)/\\item $item_tag\n\2/;
+ }
+
+ while (/\\centerline\{([^\}]+)\}\n/) {
+ local($center_text) = &deatified2verb($1);
+ s/\\centerline\{([^\}]+)\}\n/\\center $center_text\n/;
+ }
+
+ while (/\\node\{([^\}]+)\}\n/) {
+ local($node_text) = &deatified2verb($1);
+ s/\\node\{([^\}]+)\}\n/\\node $node_text\n/;
+ }
+
+ s/\\(begin|end)\{document\}\n//g;
+ s/\\begin\{description\}/\\table \\asis/g;
+ s/\\end\{description\}/\\end table/g;
+ s/\\begin\{enumerate\}/\\enumerate/g;
+ s/\\end\{enumerate\}/\\end enumerate/g;
+ s/\\begin\{itemi[sz]e\}/\\itemize \\bullet/g;
+ s/\\end\{itemi[sz]e\}/\\end itemize/g;
+ s/\\begin\{quotation\}/\\quotation/g;
+ s/\\end\{quotation\}/\\end quotation/g;
+ s/\\begin\{display\}/\n\\display/g;
+ s/\\end\{display\}/\\end display\n/g;
+ s/\\begin\{flushdisplay\}/\n\\format/g;
+ s/\\end\{flushdisplay\}/\\end format\n/g;
+ s/\\begin\{comment\}/\\quotation\nCOMMENT:-----------------------\n/g; # need more here?
+ s/\\end\{comment\}/-------------------------------\n\\end quotation/g;
+
+ # check for unknown environments (only at beginning of lines; easier)
+ # mark good ones as \begin!_/\end!_
+ # bad ones as \begin!!/\end!!
+ while (/^\\(begin|end)\{([A-Za-z]+)\}/) {
+ if ( $KNOWN_ENV{$2} ) { # good
+ s/\\(begin|end)\{([A-Za-z]+)\}/\\\1!_\{\2\}/;
+ } else { # bad
+ s/\\(begin|end)\{([A-Za-z]+)\}/\\\1!!\{\2\}/;
+ }
+ }
+ # put begin/end display around bad ones and escape magic chars
+ while (/\\(begin|end)!!\{([A-Za-z]+)\}/) {
+ local($begin_or_end) = $1;
+ local($env_name) = $2;
+
+ local($new_stuff) = "\\display\n" if $begin_or_end eq 'begin';
+ $new_stuff .= "\001backslash\003$begin_or_end\001lbrace\003$env_name\001rbrace\003\n";
+ $new_stuff .= "\\end display\n" if $begin_or_end eq 'end';
+ s/\\(begin|end)!!\{([A-Za-z]+)\}/$new_stuff/;
+ }
+ # unmark good ones
+ s/\\(begin|end)!_\{([A-Za-z]+)\}/\\\1\{\2\}/g;
+
+ local($_) = &fiddle_sectiontypes($_);
+
+ # comments were mainly handled in lit-deatify
+ s/\\\%/\%/g; # remaining percent signs needn't be escaped
+
+ # now some easy ones
+ s/\\\&/\&/g;
+ s/\\\_/\_/g;
+ s/\\\#/\#/g;
+ s/\\\$/\$/g;
+ s/\\pounds\s*([0-9\?][0-9KkMm\.\,\?]*[0-9KkMm\?])/\1 pounds/g;
+ s/\{\\em\s*/@emph\{/g;
+ s/\\\///g;
+ s/\{\\tt\s*/@kbd\{/g;
+ s/\{\\sc\s*/@sc\{/g;
+ s/``/"/g; # except the ones in \tr and \pl (sigh)
+ s/''/"/g;
+ s/\001tex-open-double-quotes\003/``/g;
+ s/\001tex-close-double-quotes\003/''/g;
+
+ s/([^\\ ])~/\1 /g; # I expect to be beaten by twiddles...
+
+ s/([^-])---([^-])/\1 -- \2/g; # I don't like what makeinfo does
+
+ # I prefer to go after specific cases, e.g., \ref's below
+ # accents
+ s/\\"\\i/i/g; # dotless i
+ s/\\"//g;
+ s/\\`//g;
+ s/\\'//g;
+ # \refs and \pagerefs
+ s/[ ~]\\ref\{/ \\xref\{/g;
+ s/^\\ref\{/\\xref\{/g;
+ s/[ ~]\\pageref\{/ \\xref\{/g; # good luck...
+ s/^\\pageref\{/\\xref\{/g;
+
+ # \xref handling must be deferred to link time
+
+ (&slashes2ats($_), (&slashes2ats($idx_real) . $idx_maybe));
+}
+
+sub slashes2ats { # and also the magic \001?\003 things put in by deatify; sigh
+ local($_) = @_;
+
+ $_ = &deatified2verb_nl($_);
+
+ s/\\/\@/g;
+ s/\001backslash\003/\\/g; # those meant to survive...
+ s/\001twiddle\003/\~/g;
+
+ $_;
+}
+
+sub texinfoize_verb {
+ local($_) = @_;
+
+ s/\@/\@\@/g;
+ s/\{/\@\{/g;
+ s/\}/\@\}/g;
+
+ $_;
+}
+
+sub texinfoize_code { # same as verb for now
+ local($_) = @_;
+
+ s/\@/\@\@/g;
+ s/\{/\@\{/g;
+ s/\}/\@\}/g;
+
+ $_;
+}
+
+sub texinfoize_table_body {
+ # is given deatified text
+ # returns text and index entries
+ local($_) = @_;
+
+ # convert &'s and \\'s to something hidden
+ s/^\&/\\tabularAnd/;
+ s/([^\\])\&/\1\\tabularAnd/g;
+ s/\\\\/\\tabularNewline/g;
+
+ local($ret_text,$ret_idxstuff) = &texinfoize_text('???','???',$_);
+ ($ret_text,$ret_idxstuff);
+}
+
+sub texinfoize_tabular {
+ local($_) = @_;
+
+ # newlines serve no purpose here
+ s/\n//g;
+
+ # split into "rows" based on \\
+ local(@row) = split(/\@tabularNewline/, $_);
+ local($r);
+
+ # find maximum column widths
+ local(@col_width) = ();
+ foreach $r (@row) {
+# $r =~ s/\\&/\001and\003/g; # avoid escaped ampersands
+ local(@row_col) = split(/\@tabularAnd/, $r);
+ local($rc_no);
+ for ($rc_no = 0; $rc_no <= $#row_col; $rc_no++) {
+ # strip leading/trailing whitespace
+ $row_col[$rc_no] =~ s/^\s+//;
+ $row_col[$rc_no] =~ s/\s+$//;
+ # \hline's throw the count off
+ $row_col[$rc_no] =~ s/\@hline//g;
+# # convert funny ampersands
+# $row_col[$rc_no] =~ s/\001and\003/&/g;
+ if (!defined($col_width[$rc_no])
+ || length($row_col[$rc_no]) > $col_width[$rc_no]) {
+ $col_width[$rc_no] = length($row_col[$rc_no]);
+ }
+ }
+ }
+ # and the total width ... (2 each for intercolumn gaps)
+ local($total_width) = 0;
+ local($cw);
+ foreach $cw (@col_width) {
+ $total_width += $cw;
+ }
+ $total_width += ($#col_width * 2);
+ local($hline_text) = ('-' x $total_width)."\n";
+
+ # now we know widths, let's make new text accordingly
+ local($outtext) = '';
+ foreach $r (@row) {
+ # escaped ampersands already under control
+ local(@row_col) = split(/\@tabularAnd/, $r);
+ local($rc_no);
+ for ($rc_no = 0; $rc_no <= $#row_col; $rc_no++) {
+ # strip leading/trailing whitespace
+ $row_col[$rc_no] =~ s/^\s+//;
+ $row_col[$rc_no] =~ s/\s+$//;
+
+ # handle \hline's (AT BEGINNING OF LINE ONLY)
+ while ($row_col[$rc_no] =~ /^\@hline\s*/) {
+ $outtext .= $hline_text;
+ $row_col[$rc_no] =~ s/^\@hline\s*//;
+ }
+ # and now the rest of the line...
+# # convert funny ampersands
+# $row_col[$rc_no] =~ s/\001and\003/&/g;
+
+ # only left justify for now
+ $outtext .= sprintf("%-".$col_width[$rc_no]."s ", $row_col[$rc_no]);
+ }
+ $outtext .= "\n";
+ }
+
+ &slashes2ats($outtext);
+}
+
+sub mk_texi_index_entry {
+ local($raw_text) = @_;
+ local(@sub_entries) = split(/\001idxsubitem\003/, $raw_text);
+ local($sube,$sortstuff,$printstuff);
+
+ foreach $sube (@sub_entries) {
+ if ($sube =~ /(.*[^\\])\001idxsort\003(.*)/) {
+ $sortstuff = $1;
+ $printstuff = $2;
+ } else {
+ $sortstuff = '';
+ $printstuff = $sube;
+ }
+ $sortstuff =~ s/\\/\001backslash\003/g;
+ $sortstuff =~ s/\@/\@\@/g;
+ $sortstuff =~ s/\{/\\\001lbrace\003/g;
+ $sortstuff =~ s/\}/\\\001rbrace\003/g;
+
+ $printstuff =~ s/\\/\001backslash\003/g;
+ $printstuff =~ s/\@/\@\@/g;
+ $printstuff =~ s/\{/\\\001lbrace\003/g;
+ $printstuff =~ s/\}/\\\001rbrace\003/g;
+
+ if ($sortstuff) {
+ $sube = "$sortstuff\\@_sep_\\@$printstuff";
+ } else {
+ $sube = $printstuff;
+ }
+ }
+ # stick it back together for makeindex
+ join(' -- ',@sub_entries);
+}
+
+sub mk_line_directive {
+ local($filename,$lineno) = @_;
+
+ ( (! $filename) ? '' : "\@srcfilename $filename\n\@srclineno $lineno\n");
+}
+
+sub std_print_code_blk {
+ local($codetxt) = @_;
+
+ # language specific
+ local($newtxt,$idx_list) = &rm_embedded_stuff($codetxt);
+
+ print "\@format\n";
+ print '-' x 70, "\n"; # 70 lets us still fit in 80 cols, even w/ some indentation
+ print &texinfoize_code($newtxt);
+ print '-' x 70, "\n";
+ print "\@end format\n";
+
+ local($i);
+ foreach $i (split(/\002/, $idx_list )) {
+ print "\@cindex ".&mk_texi_index_entry($i)."\n" if $i;
+ }
+}
+
+sub std_mk_code_frag {
+ local($codetxt) = @_;
+
+ "\@w\@samp\{" . &texinfoize_code($codetxt) . "\}\}";
+}
+
+sub gen_texinfo_table_of_contents_lines { # used by linker
+ push(@Menu_lines, "Detailed table of contents:\n\n");
+
+ local($s) = 0;
+
+ while ($s <= $#Sec_depth) {
+ next if $Sec_abs_depth[$s] <= 0 || ! $Sec_nodename[$s];
+ next if $Sec_title[$s] =~ /\001starred\003/;
+
+ # take it's numstr, throw away all the 0 pieces
+ # use the length of what's left as how much to indent
+ # (pretty terrible, eh?)
+ local($magic_str) = $Sec_numstr[$s];
+ $magic_str =~ s/^[0\.]+\.//;
+ $magic_str =~ s/\.[0\.]+$//;
+
+ push(@Menu_lines,
+ '*'.(' ' x length($magic_str)).$Sec_nodename[$s].':: '.$Sec_title[$s]."\n");
+ } continue {
+ $s++;
+ }
+}
+
+# a trailing 1 makes this file's "do"ing a success
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-2text.lprl b/web/glasgow/lit2x-0.16/literate/lit-2text.lprl
new file mode 100644
index 0000000000..54406e686c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-2text.lprl
@@ -0,0 +1,23 @@
+\section[lit2text_only]{Code used only in extracting text}
+
+Whereas \tr{lit2pgm} saves the code from a document (usually to feed
+to a compiler), \tr{lit2text} saves the raw text from a document
+(usually to feed to a spelling checker, or something similar).
+
+\begin{code}
+# still probably too simplistic
+sub spit_out_raw_text {
+
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) {
+ print "\\section$Sec_depth[$S]\[$Sec_nodespec[$S]\]\{$Sec_title[$S]\}\n";
+
+ foreach ($B = $Sec_first_blk[$S]; $B <= $Sec_last_blk[$S]; $B++) {
+
+ print $Blk_txt[$B] if $Blk_type[$B] ne 'code';
+ }
+ }
+}
+
+# this keeps 'do'ing happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-deatify.c b/web/glasgow/lit2x-0.16/literate/lit-deatify.c
new file mode 100644
index 0000000000..39386653a7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-deatify.c
@@ -0,0 +1,2084 @@
+/* A lexical scanner generated by flex */
+
+/* scanner skeleton version:
+ * $Header: /usr/fsys/odin/a/vern/flex/RCS/flex.skel,v 2.16 90/08/03 14:09:36 vern Exp $
+ */
+
+#define FLEX_SCANNER
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <osfcn.h>
+
+/* use prototypes in function declarations */
+#define YY_USE_PROTOS
+
+/* the "const" storage-class-modifier is valid */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#ifdef __STDC__
+
+#ifdef __GNUC__
+#include <stddef.h>
+void *malloc( size_t );
+void free( void* );
+#else
+#include <stdlib.h>
+#endif /* __GNUC__ */
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+
+#ifdef __TURBOC__
+#define YY_USE_CONST
+#endif
+
+
+#ifndef YY_USE_CONST
+#define const
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+/* we can't get here if it's an ANSI C compiler, or a C++ compiler,
+ * so it's got to be a K&R compiler, and therefore there's no standard
+ * place from which to include these definitions
+ */
+char *malloc();
+int free();
+int read();
+#endif
+
+
+/* amount of stuff to slurp up with each read */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* returned upon end-of-file */
+#define YY_END_TOK 0
+
+/* copy whatever the last rule matched to the standard output */
+
+/* cast to (char *) is because for 8-bit chars, yytext is (unsigned char *) */
+/* this used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite()
+ */
+#define ECHO (void) fwrite( (char *) yytext, yyleng, 1, yyout )
+
+/* gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#define YY_INPUT(buf,result,max_size) \
+ if ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+ YY_FATAL_ERROR( "read() in flex scanner failed" );
+#define YY_NULL 0
+
+/* no semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#define yyterminate() return ( YY_NULL )
+
+/* report a fatal error */
+
+/* The funky do-while is used to turn this macro definition into
+ * a single C statement (which needs a semi-colon terminator).
+ * This avoids problems with code like:
+ *
+ * if ( something_happens )
+ * YY_FATAL_ERROR( "oops, the something happened" );
+ * else
+ * everything_okay();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the YY_FATAL_ERROR() call.
+ */
+
+#define YY_FATAL_ERROR(msg) \
+ do \
+ { \
+ (void) fputs( msg, stderr ); \
+ (void) putc( '\n', stderr ); \
+ exit( 1 ); \
+ } \
+ while ( 0 )
+
+/* default yywrap function - always treat EOF as an EOF */
+#define yywrap() 1
+
+/* enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* action number for EOF rule of a given start state */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* special action meaning "start processing a new file" */
+#define YY_NEW_FILE \
+ do \
+ { \
+ yy_init_buffer( yy_current_buffer, yyin ); \
+ yy_load_buffer_state(); \
+ } \
+ while ( 0 )
+
+/* default declaration of generated scanner - a define so the user can
+ * easily add parameters
+ */
+#define YY_DECL int yylex YY_PROTO(( void ))
+
+/* code executed at the end of each rule */
+#define YY_BREAK break;
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of default input buffer */
+#endif
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+#define YY_CHAR char
+# line 1 "lit-deatify.lex"
+#define INITIAL 0
+# line 2 "lit-deatify.lex"
+#define LEX_STK_SIZE 256
+
+int lex_stk[LEX_STK_SIZE];
+int lex_stk_top = 0;
+
+#define PUSH(x) lex_stk[++lex_stk_top] = (x); BEGIN(x)
+#define POP BEGIN(lex_stk[--lex_stk_top])
+#define LEX_STK_TOP lex_stk[lex_stk_top]
+#define LEX_NEXT_TO_STK_TOP lex_stk[lex_stk_top - 1]
+#define CHG_TOP(x) lex_stk[lex_stk_top] = (x); BEGIN(x)
+#define CHG_NEXT_TO_TOP(x) lex_stk[lex_stk_top - 1] = (x)
+/* not a lot in the old stack {over,under}flow dept, what? */
+
+extern char *yytext; /* forward decl */
+void print_leading_whitespace();
+
+void
+print_lex_stk () /* just for debugging */
+{
+ int i;
+ fprintf(stderr,"lex_stk:");
+ for (i = lex_stk_top; i >= 0; i--) {
+ fprintf(stderr," %d",lex_stk[i]);
+ }
+ fprintf(stderr,"::%s\n",yytext);
+}
+int verbose; /* set from first argv */
+int follow_inputs; /* set from second argv */
+
+#if defined (SYSV) || defined (SYSV)
+#include <string.h>
+#include <time.h>
+#else
+#include <strings.h>
+#include <sys/time.h>
+#endif
+
+#if defined (SYSV)
+#define index(string, ch) strchr ((string), (ch))
+#endif
+
+#define INPUTFILE_STK_SIZE 20
+struct {
+ YY_BUFFER_STATE handle; /* flex-supplied magic */
+ char* name;
+ int lineno;
+} inputfile_stk[INPUTFILE_STK_SIZE];
+int inputfile_stk_top = 0;
+void push_inputfile();
+void pop_inputfile();
+int i; /* temporary */
+char* rbrace;
+int deatify_debug = 0;
+int unmatched_lbraces = 0;
+int unmatched_lbrackets = 0;
+
+/* like everything, must track srcfile name and lineno */
+char srcfile_name[1024]; /* too lazy to do this right */
+int lineno = 1; /* count \n's as they go by */
+int lineno_fiddled = 0; /* boolean: incr if newlines get trashed */
+
+int exit_status = 0;
+void not_OK (); /* prints an error msg and bumps exit_status */
+void warning (); /* same, but no exit-status fiddling */
+
+int lit2what; /* set from ARGV */
+
+#define IS_LIT2PGM_Q (lit2what == 1)
+#define IS_LIT2PGM (lit2what == 2)
+#define IS_LIT2TEXI (lit2what == 3)
+#define IS_LIT2LATEX (lit2what == 4)
+#define IS_LIT2DEPEND (lit2what == 5)
+#define IS_LIT2CHANGELOG (lit2what== 6)
+
+/* the condition for printing to stdout */
+#define SHLD_PRINT (! IS_LIT2PGM_Q || (LEX_STK_TOP == Code || LEX_STK_TOP == Bird))
+
+void myecho();
+#define MYECHO myecho()
+void myprintstr();
+
+#define YY_USER_ACTION if (deatify_debug) print_lex_stk(); /* debugging */
+#define Norm 1
+#define Verb 2
+#define Code 3
+#define Bird 4
+#define Atting 5
+#define Math 6
+#define Index 7
+#define Typing 8
+#define Linify_braces 9
+#define Linify_brackets 10
+# line 89 "lit-deatify.lex"
+
+/* done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext = yy_bp; \
+ yyleng = yy_cp - yy_bp; \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* return all but the first 'n' matched characters back to the input stream */
+#define yyless(n) \
+ do \
+ { \
+ /* undo effects of setting up yytext */ \
+ *yy_cp = yy_hold_char; \
+ yy_c_buf_p = yy_cp = yy_bp + n; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext )
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ YY_CHAR *yy_ch_buf; /* input buffer */
+ YY_CHAR *yy_buf_pos; /* current position in input buffer */
+
+ /* size of input buffer in bytes, not including room for EOB characters*/
+ int yy_buf_size;
+
+ /* number of characters read into yy_ch_buf, not including EOB characters */
+ int yy_n_chars;
+
+ int yy_eof_status; /* whether we've seen an EOF on this buffer */
+#define EOF_NOT_SEEN 0
+ /* "pending" happens when the EOF has been seen but there's still
+ * some text process
+ */
+#define EOF_PENDING 1
+#define EOF_DONE 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer;
+
+/* we provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state"
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed */
+static YY_CHAR yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+#ifndef YY_USER_INIT
+#define YY_USER_INIT
+#endif
+
+extern YY_CHAR *yytext;
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+YY_CHAR *yytext;
+int yyleng;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+#define YY_END_OF_BUFFER 111
+typedef int yy_state_type;
+static const short int yy_accept[398] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 111, 1, 110, 40, 39, 41, 32, 40,
+ 30, 40, 40, 40, 39, 47, 48, 47, 47, 47,
+ 53, 53, 52, 51, 63, 62, 60, 57, 58, 59,
+ 71, 70, 68, 65, 71, 71, 66, 67, 105, 104,
+ 103, 102, 89, 93, 100, 74, 78, 83, 86, 74,
+ 88, 105, 85, 74, 76, 81, 95, 74, 98, 77,
+ 82, 39, 0, 0, 0, 0, 38, 31, 36, 29,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 34, 35, 0, 12, 0, 0, 39,
+ 0, 46, 0, 0, 0, 52, 0, 0, 50, 51,
+ 51, 62, 54, 0, 70, 64, 104, 101, 87, 90,
+ 84, 73, 84, 0, 92, 0, 0, 75, 79, 80,
+ 94, 96, 97, 0, 0, 0, 11, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 39, 0,
+ 0, 50, 50, 0, 0, 0, 0, 9, 0, 10,
+ 37, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 27, 0, 0, 0, 0, 0, 39,
+
+ 0, 0, 0, 91, 72, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 39, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, 0, 28, 0, 0, 21, 0, 0, 0,
+ 0, 0, 0, 39, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33, 19, 0, 22, 0, 0,
+ 26, 0, 0, 39, 0, 0, 0, 0, 0, 13,
+ 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 14, 0,
+ 18, 0, 0, 24, 23, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 45, 0, 0, 20, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 55, 15, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 44, 25, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 2, 43, 0, 0, 0, 6, 0
+
+ } ;
+
+static const YY_CHAR yy_ec[128] =
+ { 0,
+ 1, 1, 1, 2, 2, 2, 2, 2, 3, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 5, 2, 2, 6, 7, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 2, 2, 2,
+ 2, 9, 2, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 13, 14, 2, 15, 2, 16, 17, 18, 19,
+
+ 20, 21, 22, 23, 24, 11, 11, 25, 26, 27,
+ 28, 29, 11, 30, 31, 32, 33, 34, 35, 36,
+ 37, 11, 38, 2, 39, 2, 2
+ } ;
+
+static const YY_CHAR yy_meta[40] =
+ { 0,
+ 1, 1, 2, 3, 1, 1, 1, 2, 1, 1,
+ 2, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 4
+ } ;
+
+static const short int yy_base[425] =
+ { 0,
+ 609, 608, 0, 39, 604, 4, 603, 7, 15, 18,
+ 78, 117, 156, 195, 234, 273, 18, 19, 308, 343,
+ 378, 0, 606, 611, 611, 611, 0, 33, 611, 601,
+ 611, 412, 600, 9, 573, 611, 611, 598, 581, 580,
+ 611, 31, 52, 595, 611, 0, 611, 37, 611, 611,
+ 611, 0, 611, 611, 594, 51, 611, 611, 611, 0,
+ 611, 611, 611, 611, 611, 58, 611, 611, 611, 88,
+ 611, 593, 611, 446, 611, 558, 611, 48, 557, 611,
+ 611, 0, 63, 585, 589, 588, 69, 611, 611, 611,
+ 558, 69, 83, 88, 570, 42, 573, 568, 559, 551,
+
+ 560, 108, 51, 611, 611, 580, 611, 116, 78, 565,
+ 578, 611, 554, 553, 93, 103, 110, 134, 575, 574,
+ 611, 0, 611, 550, 0, 611, 0, 611, 611, 611,
+ 611, 611, 611, 572, 131, 533, 453, 611, 611, 611,
+ 611, 611, 611, 473, 477, 476, 611, 141, 470, 445,
+ 147, 447, 447, 441, 451, 455, 451, 449, 451, 440,
+ 447, 438, 426, 445, 446, 429, 438, 123, 437, 438,
+ 436, 450, 611, 421, 147, 439, 409, 611, 442, 611,
+ 611, 419, 402, 401, 412, 403, 407, 405, 398, 403,
+ 388, 400, 395, 611, 382, 386, 387, 387, 377, 385,
+
+ 370, 369, 382, 611, 611, 377, 380, 383, 364, 374,
+ 376, 363, 386, 372, 376, 357, 364, 369, 370, 367,
+ 359, 348, 354, 125, 360, 350, 346, 347, 344, 611,
+ 353, 345, 333, 611, 332, 342, 611, 330, 339, 350,
+ 327, 326, 325, 342, 336, 329, 339, 330, 338, 317,
+ 327, 327, 313, 323, 611, 611, 312, 611, 316, 317,
+ 611, 154, 0, 336, 307, 319, 308, 318, 316, 611,
+ 297, 310, 611, 295, 302, 165, 303, 302, 304, 297,
+ 307, 287, 310, 293, 290, 305, 300, 283, 611, 290,
+ 611, 279, 173, 611, 611, 283, 290, 275, 287, 276,
+
+ 301, 299, 280, 283, 285, 261, 261, 278, 259, 276,
+ 275, 263, 260, 275, 287, 611, 0, 256, 261, 252,
+ 611, 242, 238, 611, 243, 231, 246, 249, 251, 261,
+ 245, 246, 239, 611, 611, 232, 257, 226, 231, 226,
+ 169, 227, 228, 229, 227, 249, 611, 232, 233, 226,
+ 240, 225, 218, 193, 203, 200, 201, 202, 171, 211,
+ 206, 611, 193, 207, 203, 182, 182, 188, 180, 180,
+ 201, 195, 210, 177, 182, 611, 611, 166, 154, 187,
+ 611, 184, 127, 124, 116, 208, 76, 85, 105, 611,
+ 611, 611, 50, 72, 55, 611, 611, 485, 489, 493,
+
+ 497, 501, 505, 509, 513, 28, 517, 521, 525, 529,
+ 23, 14, 1, 533, 537, 541, 545, 549, 551, 555,
+ 559, 563, 567, 571
+ } ;
+
+static const short int yy_def[425] =
+ { 0,
+ 398, 398, 399, 399, 400, 401, 400, 401, 402, 402,
+ 403, 403, 404, 404, 405, 405, 16, 16, 16, 16,
+ 16, 21, 397, 397, 397, 397, 406, 397, 397, 407,
+ 397, 397, 408, 32, 406, 397, 397, 409, 397, 397,
+ 397, 397, 397, 410, 397, 411, 397, 397, 397, 397,
+ 397, 412, 397, 397, 407, 397, 397, 397, 397, 413,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 414, 397, 397, 397, 397, 397, 74, 397, 397,
+ 397, 406, 397, 397, 415, 407, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+
+ 397, 397, 397, 397, 397, 408, 397, 397, 397, 406,
+ 409, 397, 397, 397, 397, 397, 397, 397, 416, 410,
+ 397, 411, 397, 397, 412, 397, 413, 397, 397, 397,
+ 397, 397, 397, 414, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 417, 415, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 406, 397,
+ 397, 416, 397, 397, 397, 397, 397, 397, 417, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 406,
+
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 406, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 406, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 418, 406, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 418, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+
+ 419, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 419, 397, 420, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 420,
+ 397, 397, 397, 397, 397, 397, 421, 397, 397, 397,
+ 420, 397, 397, 397, 397, 421, 397, 397, 397, 397,
+ 420, 397, 397, 397, 397, 397, 397, 397, 420, 397,
+ 397, 397, 397, 397, 397, 397, 420, 397, 397, 397,
+ 397, 397, 422, 420, 397, 397, 397, 397, 397, 422,
+ 397, 420, 397, 397, 423, 420, 397, 397, 423, 397,
+ 397, 397, 397, 424, 424, 397, 0, 397, 397, 397,
+
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397
+ } ;
+
+static const short int yy_nxt[651] =
+ { 0,
+ 26, 26, 127, 28, 26, 29, 30, 37, 26, 31,
+ 37, 26, 32, 26, 26, 125, 39, 42, 43, 40,
+ 42, 43, 59, 59, 122, 108, 44, 69, 69, 82,
+ 70, 70, 109, 115, 116, 83, 84, 26, 26, 26,
+ 26, 85, 28, 26, 29, 30, 123, 33, 31, 124,
+ 26, 34, 26, 26, 117, 118, 126, 89, 396, 141,
+ 119, 142, 128, 129, 130, 83, 144, 131, 157, 35,
+ 132, 148, 149, 158, 166, 396, 26, 26, 45, 45,
+ 163, 47, 45, 45, 45, 92, 45, 48, 394, 45,
+ 45, 45, 45, 129, 130, 115, 116, 133, 152, 151,
+
+ 132, 92, 153, 154, 168, 117, 118, 155, 390, 158,
+ 393, 119, 117, 118, 392, 49, 50, 45, 45, 390,
+ 47, 45, 45, 45, 92, 45, 48, 164, 45, 45,
+ 45, 45, 92, 175, 176, 167, 117, 118, 151, 165,
+ 92, 188, 119, 148, 149, 245, 151, 388, 92, 175,
+ 176, 199, 387, 246, 49, 50, 51, 51, 247, 53,
+ 51, 54, 55, 92, 51, 51, 164, 51, 56, 51,
+ 51, 278, 293, 341, 279, 341, 294, 151, 367, 92,
+ 293, 341, 280, 351, 294, 351, 374, 281, 386, 367,
+ 381, 382, 385, 57, 58, 51, 51, 384, 53, 51,
+
+ 54, 55, 295, 51, 51, 383, 51, 56, 51, 51,
+ 295, 391, 341, 381, 379, 367, 378, 377, 376, 375,
+ 373, 372, 351, 371, 370, 369, 368, 366, 365, 364,
+ 363, 362, 57, 58, 59, 59, 361, 61, 62, 63,
+ 64, 360, 59, 65, 359, 59, 66, 59, 59, 358,
+ 357, 356, 347, 355, 354, 353, 352, 350, 349, 348,
+ 347, 345, 344, 343, 342, 341, 340, 339, 338, 337,
+ 336, 67, 68, 59, 59, 335, 61, 62, 63, 64,
+ 334, 59, 65, 333, 59, 66, 59, 59, 332, 331,
+ 316, 329, 328, 327, 326, 325, 324, 323, 322, 321,
+
+ 320, 319, 318, 317, 316, 314, 313, 312, 311, 310,
+ 67, 68, 59, 71, 72, 309, 308, 73, 307, 306,
+ 74, 305, 304, 303, 302, 301, 300, 299, 298, 297,
+ 296, 292, 291, 290, 289, 288, 287, 286, 285, 284,
+ 283, 277, 276, 275, 274, 75, 76, 59, 71, 72,
+ 273, 272, 73, 271, 270, 74, 269, 268, 267, 266,
+ 265, 264, 263, 262, 261, 260, 259, 258, 257, 256,
+ 255, 254, 253, 252, 251, 250, 249, 248, 244, 243,
+ 75, 76, 59, 71, 72, 242, 241, 73, 240, 77,
+ 78, 79, 239, 238, 237, 236, 235, 234, 233, 232,
+
+ 231, 230, 229, 228, 227, 226, 225, 224, 223, 222,
+ 221, 220, 219, 218, 217, 80, 81, 88, 89, 216,
+ 215, 90, 214, 213, 212, 211, 210, 91, 92, 93,
+ 94, 209, 208, 207, 95, 96, 97, 98, 99, 100,
+ 101, 206, 102, 103, 92, 180, 205, 204, 203, 104,
+ 105, 129, 130, 173, 202, 133, 201, 200, 132, 198,
+ 197, 196, 195, 194, 193, 192, 191, 190, 189, 188,
+ 187, 186, 185, 184, 136, 183, 182, 137, 181, 147,
+ 180, 178, 177, 138, 139, 25, 25, 25, 25, 27,
+ 27, 27, 27, 36, 36, 36, 36, 38, 38, 38,
+
+ 38, 41, 41, 41, 41, 46, 46, 46, 46, 52,
+ 52, 52, 52, 60, 60, 60, 60, 86, 86, 86,
+ 86, 106, 106, 106, 106, 111, 111, 111, 111, 120,
+ 120, 120, 120, 134, 134, 134, 134, 146, 146, 146,
+ 146, 172, 172, 172, 172, 179, 179, 179, 179, 282,
+ 282, 315, 315, 315, 315, 330, 330, 177, 330, 346,
+ 346, 346, 346, 380, 380, 380, 380, 389, 389, 389,
+ 389, 395, 395, 395, 395, 135, 174, 121, 173, 171,
+ 170, 112, 169, 107, 163, 162, 161, 160, 159, 156,
+ 150, 87, 147, 145, 143, 140, 135, 87, 121, 114,
+
+ 113, 112, 110, 107, 87, 397, 37, 37, 24, 24,
+ 23, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397
+ } ;
+
+static const short int yy_chk[651] =
+ { 0,
+ 3, 3, 413, 3, 3, 3, 3, 6, 3, 3,
+ 8, 3, 3, 3, 3, 412, 6, 9, 9, 8,
+ 10, 10, 17, 18, 411, 34, 10, 17, 18, 406,
+ 17, 18, 34, 42, 42, 28, 28, 3, 3, 4,
+ 4, 28, 4, 4, 4, 4, 48, 4, 4, 48,
+ 4, 4, 4, 4, 43, 43, 56, 56, 395, 78,
+ 43, 78, 66, 66, 66, 83, 83, 66, 96, 4,
+ 66, 87, 87, 96, 103, 394, 4, 4, 11, 11,
+ 103, 11, 11, 11, 11, 92, 11, 11, 393, 11,
+ 11, 11, 11, 70, 70, 115, 115, 70, 93, 92,
+
+ 70, 92, 93, 94, 109, 116, 116, 94, 389, 109,
+ 388, 116, 117, 117, 387, 11, 11, 12, 12, 385,
+ 12, 12, 12, 12, 102, 12, 12, 102, 12, 12,
+ 12, 12, 108, 135, 135, 108, 118, 118, 102, 102,
+ 102, 168, 118, 148, 148, 224, 108, 384, 108, 175,
+ 175, 168, 383, 224, 12, 12, 13, 13, 224, 13,
+ 13, 13, 13, 151, 13, 13, 151, 13, 13, 13,
+ 13, 262, 276, 341, 262, 359, 276, 151, 359, 151,
+ 293, 374, 262, 341, 293, 359, 367, 262, 382, 367,
+ 380, 374, 379, 13, 13, 14, 14, 378, 14, 14,
+
+ 14, 14, 276, 14, 14, 375, 14, 14, 14, 14,
+ 293, 386, 386, 373, 372, 386, 371, 370, 369, 368,
+ 366, 365, 386, 364, 363, 361, 360, 358, 357, 356,
+ 355, 354, 14, 14, 15, 15, 353, 15, 15, 15,
+ 15, 352, 15, 15, 351, 15, 15, 15, 15, 350,
+ 349, 348, 346, 345, 344, 343, 342, 340, 339, 338,
+ 337, 336, 333, 332, 331, 330, 329, 328, 327, 326,
+ 325, 15, 15, 16, 16, 323, 16, 16, 16, 16,
+ 322, 16, 16, 320, 16, 16, 16, 16, 319, 318,
+ 315, 314, 313, 312, 311, 310, 309, 308, 307, 306,
+
+ 305, 304, 303, 302, 301, 300, 299, 298, 297, 296,
+ 16, 16, 19, 19, 19, 292, 290, 19, 288, 287,
+ 19, 286, 285, 284, 283, 282, 281, 280, 279, 278,
+ 277, 275, 274, 272, 271, 269, 268, 267, 266, 265,
+ 264, 260, 259, 257, 254, 19, 19, 20, 20, 20,
+ 253, 252, 20, 251, 250, 20, 249, 248, 247, 246,
+ 245, 244, 243, 242, 241, 240, 239, 238, 236, 235,
+ 233, 232, 231, 229, 228, 227, 226, 225, 223, 222,
+ 20, 20, 21, 21, 21, 221, 220, 21, 219, 21,
+ 21, 21, 218, 217, 216, 215, 214, 213, 212, 211,
+
+ 210, 209, 208, 207, 206, 203, 202, 201, 200, 199,
+ 198, 197, 196, 195, 193, 21, 21, 32, 32, 192,
+ 191, 32, 190, 189, 188, 187, 186, 32, 32, 32,
+ 32, 185, 184, 183, 32, 32, 32, 32, 32, 32,
+ 32, 182, 32, 32, 32, 179, 177, 176, 174, 32,
+ 32, 74, 74, 172, 171, 74, 170, 169, 74, 167,
+ 166, 165, 164, 163, 162, 161, 160, 159, 158, 157,
+ 156, 155, 154, 153, 74, 152, 150, 74, 149, 146,
+ 145, 144, 137, 74, 74, 398, 398, 398, 398, 399,
+ 399, 399, 399, 400, 400, 400, 400, 401, 401, 401,
+
+ 401, 402, 402, 402, 402, 403, 403, 403, 403, 404,
+ 404, 404, 404, 405, 405, 405, 405, 407, 407, 407,
+ 407, 408, 408, 408, 408, 409, 409, 409, 409, 410,
+ 410, 410, 410, 414, 414, 414, 414, 415, 415, 415,
+ 415, 416, 416, 416, 416, 417, 417, 417, 417, 418,
+ 418, 419, 419, 419, 419, 420, 420, 136, 420, 421,
+ 421, 421, 421, 422, 422, 422, 422, 423, 423, 423,
+ 423, 424, 424, 424, 424, 134, 124, 120, 119, 114,
+ 113, 111, 110, 106, 101, 100, 99, 98, 97, 95,
+ 91, 86, 85, 84, 79, 76, 72, 55, 44, 40,
+
+ 39, 38, 35, 33, 30, 23, 7, 5, 2, 1,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static YY_CHAR *yy_last_accepting_cpos;
+
+/* the intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+
+/* these variables are all declared out here so that section 3 code can
+ * manipulate them
+ */
+/* points to current character in buffer */
+static YY_CHAR *yy_c_buf_p = (YY_CHAR *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yyunput YY_PROTO(( YY_CHAR c, YY_CHAR *buf_ptr ));
+void yyrestart YY_PROTO(( FILE *input_file ));
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+
+#define yy_new_buffer yy_create_buffer
+
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register YY_CHAR *yy_cp, *yy_bp;
+ register int yy_act;
+
+
+ CHG_TOP(Norm); /* that's where we start */
+
+ if ( yy_init )
+ {
+ YY_USER_INIT;
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( yy_current_buffer )
+ yy_init_buffer( yy_current_buffer, yyin );
+ else
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+
+ yy_init = 0;
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* support of yytext */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of the
+ * current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ if ( yy_bp[-1] == '\n' )
+ ++yy_current_state;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[*yy_cp];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = yy_def[yy_current_state];
+ if ( yy_current_state >= 398 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 397 );
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+ YY_USER_ACTION;
+
+do_action: /* this label is used only to access EOF actions */
+
+
+ switch ( yy_act )
+ {
+ case 0: /* must backtrack */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+# line 91 "lit-deatify.lex"
+{ not_OK("ASCII chars \001, \002, \003 may not appear in literate files\n");
+ exit(1);
+ }
+ YY_BREAK
+case 2:
+# line 94 "lit-deatify.lex"
+{
+ sscanf(yytext+10,"%[^!]!_!%d", srcfile_name, &lineno);
+ if (lineno > 0) {
+ ECHO;
+ }
+ }
+ YY_BREAK
+case 3:
+# line 100 "lit-deatify.lex"
+{ lineno++;
+ if (follow_inputs) {
+ /* nullify first right brace */
+ rbrace = index(yytext+7,'}');
+ *rbrace = '\0';
+ push_inputfile(yytext+7);
+ } else {
+ MYECHO;
+ }
+ }
+ YY_BREAK
+case YY_STATE_EOF(Norm):
+case YY_STATE_EOF(Bird):
+# line 110 "lit-deatify.lex"
+{ if ( inputfile_stk_top <= 0 ) {
+ yyterminate();
+ } else {
+ pop_inputfile();
+ }
+ CHG_TOP(Norm); /* revert */
+ }
+ YY_BREAK
+case 5:
+# line 118 "lit-deatify.lex"
+case 6:
+# line 119 "lit-deatify.lex"
+case 7:
+# line 119 "lit-deatify.lex"
+{ lineno++; MYECHO; PUSH(Verb); /* some may have opt arg */ }
+ YY_BREAK
+case 8:
+# line 120 "lit-deatify.lex"
+{ lineno++;
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+ MYECHO;
+ PUSH(Code);
+ }
+ YY_BREAK
+case 9:
+# line 127 "lit-deatify.lex"
+{ /* convert to something less weird & try again */
+ unput('>'); unput('\n'); unput('\n');
+ }
+ YY_BREAK
+case 10:
+# line 130 "lit-deatify.lex"
+{ lineno += 3;
+ /* NB: init > converted to space */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+3);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+ YY_BREAK
+case 11:
+# line 140 "lit-deatify.lex"
+{ lineno++; /* so msg will have right line # */
+ if (lineno > 2) /* I feel guilty about this hack */
+ /* to avoid: file is: blank lines, then code */
+ not_OK("Bird-style code not preceded by a blank line\n");
+ lineno++; /* account for other \n */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+2);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+ YY_BREAK
+case 12:
+# line 153 "lit-deatify.lex"
+{ lineno++; /* first line of file */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+1);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+ YY_BREAK
+case 13:
+# line 162 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 14:
+# line 163 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 15:
+# line 164 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 16:
+# line 165 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 17:
+# line 166 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 18:
+# line 167 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 19:
+# line 168 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 20:
+# line 169 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 21:
+# line 170 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 22:
+# line 171 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 23:
+# line 172 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 24:
+# line 173 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_brackets); }
+ YY_BREAK
+case 25:
+# line 174 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 26:
+# line 175 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 27:
+# line 176 "lit-deatify.lex"
+{ MYECHO; unmatched_lbraces = 1; PUSH(Typing);
+ /* \tr has braces as literals */
+ }
+ YY_BREAK
+case 28:
+# line 179 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_brackets); }
+ YY_BREAK
+case 29:
+# line 180 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 30:
+# line 181 "lit-deatify.lex"
+{ myprintstr("\\codeInText{"); PUSH(Atting); }
+ YY_BREAK
+case 31:
+# line 182 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 32:
+# line 183 "lit-deatify.lex"
+{ myprintstr("\\MathMode{"); PUSH(Math); }
+ YY_BREAK
+case 33:
+# line 184 "lit-deatify.lex"
+{ MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Index);
+ }
+ YY_BREAK
+case 34:
+# line 188 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 35:
+# line 189 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 36:
+# line 190 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 37:
+# line 191 "lit-deatify.lex"
+{ /* technically this Bird-style code is wrong
+ (no blank line in front of it, but that's
+ not intuitively obvious to the casual observer).
+ Solution? A hack!
+ */
+ unput('>'); unput('\n'); unput('\n');
+ }
+ YY_BREAK
+case 38:
+# line 198 "lit-deatify.lex"
+{ /* throw away */ lineno++;
+ if (! IS_LIT2PGM_Q)
+ printf("\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+ YY_BREAK
+case 39:
+# line 202 "lit-deatify.lex"
+{ MYECHO; /* slight efficiency */ }
+ YY_BREAK
+case 40:
+# line 203 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 41:
+# line 204 "lit-deatify.lex"
+{ /* handle line-number fiddling */
+ MYECHO;
+ lineno++;
+ if (lineno_fiddled) {
+ if (! IS_LIT2PGM_Q)
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ lineno_fiddled = 0;
+ }
+ }
+ YY_BREAK
+case 42:
+# line 214 "lit-deatify.lex"
+case 43:
+# line 215 "lit-deatify.lex"
+case 44:
+# line 215 "lit-deatify.lex"
+{ MYECHO; POP; }
+ YY_BREAK
+case 45:
+# line 216 "lit-deatify.lex"
+{ if (! IS_LIT2PGM_Q) ECHO; POP; }
+ YY_BREAK
+case 46:
+# line 217 "lit-deatify.lex"
+{ lineno++; MYECHO; /* a line not started by \ */}
+ YY_BREAK
+case 47:
+# line 218 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 48:
+# line 219 "lit-deatify.lex"
+{ lineno++; MYECHO; }
+ YY_BREAK
+case YY_STATE_EOF(Verb):
+case YY_STATE_EOF(Code):
+# line 220 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file in verbatim text or (pseudo)code\n");
+ exit(1);
+ }
+ YY_BREAK
+case 50:
+# line 223 "lit-deatify.lex"
+{ /* whitespace/blank-lines do not matter */
+ /* count lines... */
+ for (i = 0; i < strlen(yytext); i++) {
+ if (yytext[i] == '\n')
+ lineno++;
+ }
+ if (! IS_LIT2PGM_Q) {
+ ECHO;
+ } else { /* don't print leading whitestuff */
+ for (i = 0; i < strlen(yytext) && yytext[i] != '>'; i++)
+ ; /* no-op */
+ /* report where this got us...*/
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,
+ ((yytext[yyleng-1] == '\n') ? (lineno-1) : lineno));
+ /* putchar(' '); convert leading > to space */
+ for ( i++ ; i < strlen(yytext); i++)
+ putchar(yytext[i]);
+ }
+ }
+ YY_BREAK
+case 51:
+# line 242 "lit-deatify.lex"
+{ if (yytext[yyleng-1] == '\n') { lineno++; }
+ if (IS_LIT2PGM_Q) printf("%s",yytext+1); else ECHO;
+ }
+ YY_BREAK
+case 52:
+# line 245 "lit-deatify.lex"
+{ lineno++;
+ if ( ! IS_LIT2PGM_Q) ECHO;
+ POP;
+ }
+ YY_BREAK
+case 53:
+# line 249 "lit-deatify.lex"
+{ lineno--; /* to get right # on msg */
+ not_OK("Bird-style code not followed by a blank line\n");
+ lineno++; /* put it back */
+ unput(yytext[0]);
+ POP;
+ }
+ YY_BREAK
+case 54:
+# line 255 "lit-deatify.lex"
+{ myprintstr("@"); }
+ YY_BREAK
+case 55:
+# line 257 "lit-deatify.lex"
+case 56:
+# line 257 "lit-deatify.lex"
+{ myprintstr("\001noindex\003}");
+ POP;
+ }
+ YY_BREAK
+case 57:
+# line 260 "lit-deatify.lex"
+{ myprintstr("}");
+ POP;
+ }
+ YY_BREAK
+case 58:
+# line 263 "lit-deatify.lex"
+{ myprintstr("\001lbrace\003"); }
+ YY_BREAK
+case 59:
+# line 264 "lit-deatify.lex"
+{ myprintstr("\001rbrace\003"); }
+ YY_BREAK
+case 60:
+# line 265 "lit-deatify.lex"
+{ warning("I'm turning a newline inside a @...@ into a space\n");
+ myprintstr(" ");
+ lineno++;
+ }
+ YY_BREAK
+case YY_STATE_EOF(Atting):
+# line 270 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file inside an @ ... @\n");
+ exit(1);
+ }
+ YY_BREAK
+case 62:
+# line 273 "lit-deatify.lex"
+{ MYECHO; /* tiny efficiency */ }
+ YY_BREAK
+case 63:
+# line 274 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 64:
+# line 275 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 65:
+# line 276 "lit-deatify.lex"
+{ myprintstr("}");
+ POP;
+ }
+ YY_BREAK
+case 66:
+# line 279 "lit-deatify.lex"
+{ myprintstr("\001lbrace\003"); }
+ YY_BREAK
+case 67:
+# line 280 "lit-deatify.lex"
+{ myprintstr("\001rbrace\003"); }
+ YY_BREAK
+case 68:
+# line 281 "lit-deatify.lex"
+{ myprintstr("\001newline\003");
+ lineno++;
+ }
+ YY_BREAK
+case YY_STATE_EOF(Math):
+# line 285 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file inside $ ... $ (math mode)\n");
+ exit(1);
+ }
+ YY_BREAK
+case 70:
+# line 288 "lit-deatify.lex"
+{ MYECHO; /* tiny efficiency */ }
+ YY_BREAK
+case 71:
+# line 289 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 72:
+# line 290 "lit-deatify.lex"
+{
+ MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Typing);
+ }
+ YY_BREAK
+case 73:
+# line 296 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 74:
+# line 299 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 75:
+# line 302 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 76:
+# line 306 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_braces); }
+ YY_BREAK
+case 77:
+# line 307 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 78:
+# line 309 "lit-deatify.lex"
+{ unmatched_lbraces++; myprintstr("\001lbrace\003"); }
+ YY_BREAK
+case 79:
+# line 311 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 80:
+# line 314 "lit-deatify.lex"
+{ /* next arg */ MYECHO; }
+ YY_BREAK
+case 81:
+# line 316 "lit-deatify.lex"
+{ MYECHO; POP; }
+ YY_BREAK
+case 82:
+# line 317 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 83:
+# line 319 "lit-deatify.lex"
+{ if (--unmatched_lbraces == 0) {
+ MYECHO;
+ POP;
+ } else {
+ myprintstr("\001rbrace\003");
+ }
+ }
+ YY_BREAK
+case 84:
+# line 327 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 85:
+# line 330 "lit-deatify.lex"
+{
+ myprintstr("\\codeInText{"); /* no newline */
+ PUSH(Atting);
+ }
+ YY_BREAK
+case 86:
+# line 334 "lit-deatify.lex"
+{ MYECHO; /* NB: magic <Index> chars below */ }
+ YY_BREAK
+case 87:
+# line 336 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 88:
+# line 339 "lit-deatify.lex"
+{
+ myprintstr("\\MathMode{"); /* no newline */
+ PUSH(Math);
+ }
+ YY_BREAK
+case 89:
+# line 343 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 90:
+# line 345 "lit-deatify.lex"
+{
+ MYECHO;
+ }
+ YY_BREAK
+case 91:
+# line 348 "lit-deatify.lex"
+{
+ /* see earlier comments about crimes against humanity */
+ unput('>'); unput('\n'); unput('\n');
+ }
+ YY_BREAK
+case 92:
+# line 352 "lit-deatify.lex"
+{ /* throw away */
+ lineno++;
+ lineno_fiddled++;
+ }
+ YY_BREAK
+case 93:
+# line 356 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 94:
+# line 358 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 95:
+# line 359 "lit-deatify.lex"
+{ MYECHO; PUSH(Linify_brackets); }
+ YY_BREAK
+case 96:
+# line 361 "lit-deatify.lex"
+{ myprintstr("\\\001rbracket\003"); /* cannot have these in the way */ }
+ YY_BREAK
+case 97:
+# line 362 "lit-deatify.lex"
+{ if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003\{");
+ not_OK("WHAT'S GOING ON? ]{\n");
+ print_lex_stk();
+ }
+ CHG_TOP(Linify_braces);
+ }
+ YY_BREAK
+case 98:
+# line 371 "lit-deatify.lex"
+{ if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003");
+ }
+ POP;
+ }
+ YY_BREAK
+case 99:
+# line 379 "lit-deatify.lex"
+{ MYECHO; /* my pseudo-makeindex has two magic chars */ }
+ YY_BREAK
+case 100:
+# line 380 "lit-deatify.lex"
+{ myprintstr("\001idxsort\003"); }
+ YY_BREAK
+case 101:
+# line 381 "lit-deatify.lex"
+{ MYECHO; }
+ YY_BREAK
+case 102:
+# line 382 "lit-deatify.lex"
+{ myprintstr("\001idxsubitem\003"); }
+ YY_BREAK
+case 103:
+# line 384 "lit-deatify.lex"
+{
+ lineno++;
+ lineno_fiddled++;
+ if (LEX_STK_TOP == Index) {
+ warning("I'm turning a newline inside an \\index{...} into a space\n");
+ myprintstr(" ");
+ } else if (LEX_STK_TOP == Typing) {
+ warning("I'm turning a newline inside a \\tr{...} or \\pl{...} into a space\n");
+ myprintstr(" ");
+ } else {
+ myprintstr("\001newline\003");
+ }
+ }
+ YY_BREAK
+case 104:
+# line 398 "lit-deatify.lex"
+{
+ MYECHO; /* tiny efficiency */
+ }
+ YY_BREAK
+case 105:
+# line 402 "lit-deatify.lex"
+{ MYECHO; /* catch all */ }
+ YY_BREAK
+case YY_STATE_EOF(Index):
+# line 404 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file inside an \\index{...}\n");
+ exit(1);
+ }
+ YY_BREAK
+case YY_STATE_EOF(Linify_braces):
+# line 407 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file inside a macro argument\n");
+ exit(1);
+ }
+ YY_BREAK
+case YY_STATE_EOF(Linify_brackets):
+# line 410 "lit-deatify.lex"
+{not_OK("unexpected end-of-file inside a macro optional argument\n");
+ exit(1);
+ }
+ YY_BREAK
+case YY_STATE_EOF(Typing):
+# line 413 "lit-deatify.lex"
+{ not_OK("unexpected end-of-file inside a \\tr{...}\n");
+ exit(1);
+ }
+ YY_BREAK
+case 110:
+# line 416 "lit-deatify.lex"
+ECHO;
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* amount of text matched not including the EOB char */
+ int yy_amount_of_matched_text = yy_cp - yytext - 1;
+
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+
+ /* note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the end-
+ * of-buffer state). Contrast this with the test in yyinput().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* this was really a NUL */
+ {
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* okay, we're now positioned to make the
+ * NUL transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we
+ * don't want to build jamming into it because
+ * then it will run more slowly)
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* consume the NUL */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* note: because we've taken care in
+ * yy_get_next_buffer() to have set up yytext,
+ * we can now set up yy_c_buf_p so that if some
+ * total hoser (like flex itself) wants
+ * to call the scanner after we return the
+ * YY_NULL, it'll still work - another YY_NULL
+ * will get returned.
+ */
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF((yy_start - 1) / 2);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ }
+ break;
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+#ifdef FLEX_DEBUG
+ printf( "action # %d\n", yy_act );
+#endif
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ }
+ }
+ }
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * synopsis
+ * int yy_get_next_buffer();
+ *
+ * returns a code representing an action
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+
+ {
+ register YY_CHAR *dest = yy_current_buffer->yy_ch_buf;
+ register YY_CHAR *source = yytext - 1; /* copy prev. char, too */
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ /* try to read more data */
+
+ /* first move last chars to start of buffer */
+ number_to_move = yy_c_buf_p - yytext;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_eof_status != EOF_NOT_SEEN )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ else if ( num_to_read <= 0 )
+ YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" );
+
+ /* read in more data */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == 1 )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yy_current_buffer->yy_eof_status = EOF_DONE;
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_eof_status = EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ /* yytext begins at the second character in yy_ch_buf; the first
+ * character is the one which preceded it before reading in the latest
+ * buffer; it needs to be kept around in case it's a newline, so
+ * yy_get_previous_state() will have with '^' rules active
+ */
+
+ yytext = &yy_current_buffer->yy_ch_buf[1];
+
+ return ( ret_val );
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached
+ *
+ * synopsis
+ * yy_state_type yy_get_previous_state();
+ */
+
+static yy_state_type yy_get_previous_state()
+
+ {
+ register yy_state_type yy_current_state;
+ register YY_CHAR *yy_cp;
+
+ register YY_CHAR *yy_bp = yytext;
+
+ yy_current_state = yy_start;
+ if ( yy_bp[-1] == '\n' )
+ ++yy_current_state;
+
+ for ( yy_cp = yytext + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[*yy_cp] : 2);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = yy_def[yy_current_state];
+ if ( yy_current_state >= 398 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ }
+
+ return ( yy_current_state );
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( register yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+register yy_state_type yy_current_state;
+#endif
+
+ {
+ register int yy_is_jam;
+ register YY_CHAR *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 2;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = yy_def[yy_current_state];
+ if ( yy_current_state >= 398 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 397);
+
+ return ( yy_is_jam ? 0 : yy_current_state );
+ }
+
+
+#ifdef YY_USE_PROTOS
+static void yyunput( YY_CHAR c, register YY_CHAR *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+YY_CHAR c;
+register YY_CHAR *yy_bp;
+#endif
+
+ {
+ register YY_CHAR *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
+ register YY_CHAR *dest =
+ &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size + 2];
+ register YY_CHAR *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += dest - source;
+ yy_bp += dest - source;
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ if ( yy_cp > yy_bp && yy_cp[-1] == '\n' )
+ yy_cp[-2] = '\n';
+
+ *--yy_cp = c;
+
+ /* note: the formal parameter *must* be called "yy_bp" for this
+ * macro to now work correctly
+ */
+ YY_DO_BEFORE_ACTION; /* set up yytext again */
+ }
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+
+ {
+ int c;
+ YY_CHAR *yy_cp = yy_c_buf_p;
+
+ *yy_cp = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* this was really a NUL */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ yytext = yy_c_buf_p;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ {
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+ return ( EOF );
+ }
+
+ YY_NEW_FILE;
+
+#ifdef __cplusplus
+ return ( yyinput() );
+#else
+ return ( input() );
+#endif
+ }
+ break;
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+ break;
+
+ case EOB_ACT_LAST_MATCH:
+#ifdef __cplusplus
+ YY_FATAL_ERROR( "unexpected last match in yyinput()" );
+#else
+ YY_FATAL_ERROR( "unexpected last match in input()" );
+#endif
+ }
+ }
+ }
+
+ c = *yy_c_buf_p;
+ yy_hold_char = *++yy_c_buf_p;
+
+ return ( c );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+
+ {
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* flush out information for old buffer */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* we don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) malloc( sizeof( struct yy_buffer_state ) );
+
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (YY_CHAR *) malloc( (unsigned) (b->yy_buf_size + 2) );
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ yy_init_buffer( b, file );
+
+ return ( b );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ free( (char *) b->yy_ch_buf );
+ free( (char *) b );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+ {
+ b->yy_input_file = file;
+
+ /* we put in the '\n' and start reading from [1] so that an
+ * initial match-at-newline will be true.
+ */
+
+ b->yy_ch_buf[0] = '\n';
+ b->yy_n_chars = 1;
+
+ /* we always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[1];
+
+ b->yy_eof_status = EOF_NOT_SEEN;
+ }
+# line 416 "lit-deatify.lex"
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ if (argc != 5) {
+ fprintf(stderr,"Sorry, %s must have exactly 4 arguments\n", argv[0]);
+ exit(1);
+ }
+ verbose = argv[1][0] - '0'; /* hacks */
+ follow_inputs = argv[2][0] - '0';
+ lit2what = argv[3][0] - '0'; /* used in IS_LIT2xxx tests */
+ if (strcmp(argv[4], "-") == 0) {
+ yyin = stdin;
+ } else if ((yyin = fopen(argv[4], "r")) == NULL) {
+ fprintf(stderr,"%s: can't open file %s\n", argv[0], argv[4]);
+ exit(1);
+ }
+ strcpy(srcfile_name, argv[4]);
+ inputfile_stk[ inputfile_stk_top /* 0 */ ].name = argv[4];
+ if ( ! IS_LIT2PGM_Q ) printf("srcfile!_!%s!_!1!_!\n",argv[4]);
+ yylex();
+ exit(exit_status);
+}
+
+void
+push_inputfile (fname)
+char* fname;
+{
+ if ( inputfile_stk_top >= INPUTFILE_STK_SIZE ) {
+ fprintf(stderr,"\\input's too deeply nested\n");
+ exit(1);
+ }
+
+ /* record where we are in current file */
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+ inputfile_stk[ inputfile_stk_top ].handle = YY_CURRENT_BUFFER;
+ /* actual push */
+ inputfile_stk_top++;
+
+ /* open new file fname */
+ if ((yyin = fopen(fname, "r")) == NULL) {
+ fprintf(stderr,"%s:%d: can't open \\input file %s\n", srcfile_name, lineno, fname);
+ exit(1);
+ }
+ yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) );
+
+ /* report that's where we are */
+ if (! IS_LIT2PGM_Q) printf("srcfile!_!%s!_!1!_!\n",fname);
+ /* set srcfile_name and lineno for new file */
+
+ strcpy(srcfile_name, fname); /* for my own tracking */
+ lineno = 1;
+
+ /* push/record everything for new file */
+ inputfile_stk[ inputfile_stk_top ].name = srcfile_name;
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+}
+
+void
+pop_inputfile ()
+{
+ inputfile_stk_top--; /* actual pop */
+
+ /* remind where we were */
+ strcpy(srcfile_name, inputfile_stk[inputfile_stk_top].name);
+ lineno = inputfile_stk[inputfile_stk_top].lineno;
+ /* put in an extra newline or two before the next file;
+ otherwise, the cat'ting of files gives things like:
+
+ > last line of code
+ \section{Next section}
+
+ which happens to be very bad for lit2stuff.
+ */
+ if (! IS_LIT2PGM_Q) printf("\n\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+
+ /* return to prev inputfile */
+ yy_switch_to_buffer( inputfile_stk[inputfile_stk_top].handle );
+}
+
+void
+myecho ()
+{
+ myprintstr(yytext);
+}
+
+void
+myprintstr (str)
+char *str;
+{
+ if (SHLD_PRINT) {
+ printf("%s",str);
+ }
+}
+
+void
+print_leading_whitespace ()
+{
+ int i;
+
+ for (i = 0; yytext[i] == ' ' || yytext[i] == '\t'; i++) {
+ putchar(yytext[i]);
+ }
+}
+
+void
+not_OK(msg)
+char *msg;
+{
+ /* a good old emacsable error msg */
+ fprintf(stderr,"%s:%d: %s", srcfile_name, lineno, msg);
+ exit_status++;
+}
+
+void
+warning(msg) /* exit_status not fiddled */
+char *msg;
+{
+ /* a good old emacsable warning msg */
+ fprintf(stderr,"%s:%d: [warning] %s", srcfile_name, lineno, msg);
+}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-deatify.lex b/web/glasgow/lit2x-0.16/literate/lit-deatify.lex
new file mode 100644
index 0000000000..8f4079fedc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-deatify.lex
@@ -0,0 +1,538 @@
+%{
+#define LEX_STK_SIZE 256
+
+int lex_stk[LEX_STK_SIZE];
+int lex_stk_top = 0;
+
+#define PUSH(x) lex_stk[++lex_stk_top] = (x); BEGIN(x)
+#define POP BEGIN(lex_stk[--lex_stk_top])
+#define LEX_STK_TOP lex_stk[lex_stk_top]
+#define LEX_NEXT_TO_STK_TOP lex_stk[lex_stk_top - 1]
+#define CHG_TOP(x) lex_stk[lex_stk_top] = (x); BEGIN(x)
+#define CHG_NEXT_TO_TOP(x) lex_stk[lex_stk_top - 1] = (x)
+/* not a lot in the old stack {over,under}flow dept, what? */
+
+extern char *yytext; /* forward decl */
+void print_leading_whitespace();
+
+void
+print_lex_stk () /* just for debugging */
+{
+ int i;
+ fprintf(stderr,"lex_stk:");
+ for (i = lex_stk_top; i >= 0; i--) {
+ fprintf(stderr," %d",lex_stk[i]);
+ }
+ fprintf(stderr,"::%s\n",yytext);
+}
+int verbose; /* set from first argv */
+int follow_inputs; /* set from second argv */
+
+#if defined (SYSV) || defined (SYSV)
+#include <string.h>
+#include <time.h>
+#else
+#include <strings.h>
+#include <sys/time.h>
+#endif
+
+#if defined (SYSV)
+#define index(string, ch) strchr ((string), (ch))
+#endif
+
+#define INPUTFILE_STK_SIZE 20
+struct {
+ YY_BUFFER_STATE handle; /* flex-supplied magic */
+ char* name;
+ int lineno;
+} inputfile_stk[INPUTFILE_STK_SIZE];
+int inputfile_stk_top = 0;
+void push_inputfile();
+void pop_inputfile();
+int i; /* temporary */
+char* rbrace;
+int deatify_debug = 0;
+int unmatched_lbraces = 0;
+int unmatched_lbrackets = 0;
+
+/* like everything, must track srcfile name and lineno */
+char srcfile_name[1024]; /* too lazy to do this right */
+int lineno = 1; /* count \n's as they go by */
+int lineno_fiddled = 0; /* boolean: incr if newlines get trashed */
+
+int exit_status = 0;
+void not_OK (); /* prints an error msg and bumps exit_status */
+void warning (); /* same, but no exit-status fiddling */
+
+int lit2what; /* set from ARGV */
+
+#define IS_LIT2PGM_Q (lit2what == 1)
+#define IS_LIT2PGM (lit2what == 2)
+#define IS_LIT2TEXI (lit2what == 3)
+#define IS_LIT2LATEX (lit2what == 4)
+#define IS_LIT2DEPEND (lit2what == 5)
+#define IS_LIT2CHANGELOG (lit2what== 6)
+
+/* the condition for printing to stdout */
+#define SHLD_PRINT (! IS_LIT2PGM_Q || (LEX_STK_TOP == Code || LEX_STK_TOP == Bird))
+
+void myecho();
+#define MYECHO myecho()
+void myprintstr();
+
+#define YY_USER_ACTION if (deatify_debug) print_lex_stk(); /* debugging */
+%}
+D [0-9]+
+END_WORD [-~/!\?(),\.'`A-Za-z0-9]*[ \t]*
+
+%x Norm Verb Code Bird Atting Math Index Typing Linify_braces Linify_brackets
+%%
+ CHG_TOP(Norm); /* that's where we start */
+[\001\002\003] { not_OK("ASCII chars \001, \002, \003 may not appear in literate files\n");
+ exit(1);
+ }
+<Norm>^"srcfile!_!"(.+)"!_!"([0-9]+)"!_!"\n {
+ sscanf(yytext+10,"%[^!]!_!%d", srcfile_name, &lineno);
+ if (lineno > 0) {
+ ECHO;
+ }
+ }
+<Norm>^\\input\{[^\}\n]+\}.*\n { lineno++;
+ if (follow_inputs) {
+ /* nullify first right brace */
+ rbrace = index(yytext+7,'}');
+ *rbrace = '\0';
+ push_inputfile(yytext+7);
+ } else {
+ MYECHO;
+ }
+ }
+<Norm,Bird><<EOF>> { if ( inputfile_stk_top <= 0 ) {
+ yyterminate();
+ } else {
+ pop_inputfile();
+ }
+ CHG_TOP(Norm); /* revert */
+ }
+<Norm>^\\begin\{verbatim\}.*\n |
+<Norm>^\\begin\{flushverbatim\}.*\n |
+<Norm>^\\begin\{pseudocode\}.*\n { lineno++; MYECHO; PUSH(Verb); /* some may have opt arg */ }
+<Norm>^\\begin\{code\}.*\n { lineno++;
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+ MYECHO;
+ PUSH(Code);
+ }
+<Norm>\n[ \t]+\n\> { /* convert to something less weird & try again */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Norm>\n\n\>.*\n { lineno += 3;
+ /* NB: init > converted to space */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+3);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+<Norm>\n\>.*\n { lineno++; /* so msg will have right line # */
+ if (lineno > 2) /* I feel guilty about this hack */
+ /* to avoid: file is: blank lines, then code */
+ not_OK("Bird-style code not preceded by a blank line\n");
+ lineno++; /* account for other \n */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+2);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+<Norm>^\>.*\n { lineno++; /* first line of file */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+1);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+<Norm>\\author\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\caption\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\centerline\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\date\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\define\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\heading\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\label\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\menuentry\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\node\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\owner\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\[sub]*section{D}?\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\[sub]*section{D}?\[ { MYECHO; PUSH(Linify_brackets); }
+<Norm>\\standaloneornot\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\title\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\(tr|pl)\{ { MYECHO; unmatched_lbraces = 1; PUSH(Typing);
+ /* \tr has braces as literals */
+ }
+<Norm>\\item\[ { MYECHO; PUSH(Linify_brackets); }
+<Norm>\\@ { MYECHO; }
+<Norm>@ { myprintstr("\\codeInText{"); PUSH(Atting); }
+<Norm>\\\$ { MYECHO; }
+<Norm>\$ { myprintstr("\\MathMode{"); PUSH(Math); }
+<Norm>\\index\{ { MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Index);
+ }
+<Norm>\\\{ { MYECHO; }
+<Norm>\\\} { MYECHO; }
+<Norm,Math>\\% { MYECHO; }
+<Norm,Math>\%.*\n[ \t]*\n> { /* technically this Bird-style code is wrong
+ (no blank line in front of it, but that's
+ not intuitively obvious to the casual observer).
+ Solution? A hack!
+ */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Norm,Math>\%.*\n { /* throw away */ lineno++;
+ if (! IS_LIT2PGM_Q)
+ printf("\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+<Norm>[A-Za-z0-9 \t]+ { MYECHO; /* slight efficiency */ }
+<Norm>. { MYECHO; }
+<Norm>\n { /* handle line-number fiddling */
+ MYECHO;
+ lineno++;
+ if (lineno_fiddled) {
+ if (! IS_LIT2PGM_Q)
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ lineno_fiddled = 0;
+ }
+ }
+<Verb>^\\end\{verbatim\} |
+<Verb>^\\end\{flushverbatim\} |
+<Verb>^\\end\{pseudocode\} { MYECHO; POP; }
+<Code>^\\end\{code\} { if (! IS_LIT2PGM_Q) ECHO; POP; }
+<Verb,Code>^[^\\\n].*\n { lineno++; MYECHO; /* a line not started by \ */}
+<Verb,Code>. { MYECHO; }
+<Verb,Code>\n { lineno++; MYECHO; }
+<Verb,Code><<EOF>> { not_OK("unexpected end-of-file in verbatim text or (pseudo)code\n");
+ exit(1);
+ }
+<Bird>[ \t\n]*\n\>.*\n? { /* whitespace/blank-lines do not matter */
+ /* count lines... */
+ for (i = 0; i < strlen(yytext); i++) {
+ if (yytext[i] == '\n')
+ lineno++;
+ }
+ if (! IS_LIT2PGM_Q) {
+ ECHO;
+ } else { /* don't print leading whitestuff */
+ for (i = 0; i < strlen(yytext) && yytext[i] != '>'; i++)
+ ; /* no-op */
+ /* report where this got us...*/
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,
+ ((yytext[yyleng-1] == '\n') ? (lineno-1) : lineno));
+ /* putchar(' '); convert leading > to space */
+ for ( i++ ; i < strlen(yytext); i++)
+ putchar(yytext[i]);
+ }
+ }
+<Bird>^\>.*\n? { if (yytext[yyleng-1] == '\n') { lineno++; }
+ if (IS_LIT2PGM_Q) printf("%s",yytext+1); else ECHO;
+ }
+<Bird>[ \t]*\n { lineno++;
+ if ( ! IS_LIT2PGM_Q) ECHO;
+ POP;
+ }
+<Bird>. { lineno--; /* to get right # on msg */
+ not_OK("Bird-style code not followed by a blank line\n");
+ lineno++; /* put it back */
+ unput(yytext[0]);
+ POP;
+ }
+<Atting>@@ { myprintstr("@"); }
+<Atting>@\\noindex\{\} |
+<Atting>@\\noindex { myprintstr("\001noindex\003}");
+ POP;
+ }
+<Atting>@ { myprintstr("}");
+ POP;
+ }
+<Atting>\{ { myprintstr("\001lbrace\003"); }
+<Atting>\} { myprintstr("\001rbrace\003"); }
+<Atting>\n { warning("I'm turning a newline inside a @...@ into a space\n");
+ myprintstr(" ");
+ lineno++;
+ }
+
+<Atting><<EOF>> { not_OK("unexpected end-of-file inside an @ ... @\n");
+ exit(1);
+ }
+<Atting>[A-Za-z0-9 \t]+ { MYECHO; /* tiny efficiency */ }
+<Atting>. { MYECHO; }
+<Math>\\\$ { MYECHO; }
+<Math>\$ { myprintstr("}");
+ POP;
+ }
+<Math>\{ { myprintstr("\001lbrace\003"); }
+<Math>\} { myprintstr("\001rbrace\003"); }
+<Math>\n { myprintstr("\001newline\003");
+ lineno++;
+ }
+
+<Math><<EOF>> { not_OK("unexpected end-of-file inside $ ... $ (math mode)\n");
+ exit(1);
+ }
+<Math>[A-Za-z0-9 \t]+ { MYECHO; /* tiny efficiency */ }
+<Math>. { MYECHO; }
+<Linify_braces,Linify_brackets>\\(tr|pl)\{ {
+ MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Typing);
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\\\ {
+ MYECHO;
+ }
+<Index,Linify_braces,Linify_brackets,Typing>\\ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\\\{ {
+ MYECHO;
+ }
+
+<Linify_braces>\{ { MYECHO; PUSH(Linify_braces); }
+<Linify_brackets>\{ { MYECHO; }
+
+<Index,Typing>\{ { unmatched_lbraces++; myprintstr("\001lbrace\003"); }
+
+<Linify_braces,Linify_brackets>\\\} {
+ MYECHO;
+ }
+<Linify_braces>\}\{ { /* next arg */ MYECHO; }
+
+<Linify_braces>\} { MYECHO; POP; }
+<Linify_brackets>\} { MYECHO; }
+
+<Index,Typing>\} { if (--unmatched_lbraces == 0) {
+ MYECHO;
+ POP;
+ } else {
+ myprintstr("\001rbrace\003");
+ }
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\@ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>@ {
+ myprintstr("\\codeInText{"); /* no newline */
+ PUSH(Atting);
+ }
+<Typing>@ { MYECHO; /* NB: magic <Index> chars below */ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\\$ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\$ {
+ myprintstr("\\MathMode{"); /* no newline */
+ PUSH(Math);
+ }
+<Index,Typing>\$ { MYECHO; }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\% {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\%.*\n[ \t]*\n> {
+ /* see earlier comments about crimes against humanity */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Linify_braces,Linify_brackets>\%.*\n { /* throw away */
+ lineno++;
+ lineno_fiddled++;
+ }
+<Index,Typing>% { MYECHO; }
+
+<Linify_brackets>\\\[ { MYECHO; }
+<Linify_brackets>\[ { MYECHO; PUSH(Linify_brackets); }
+
+<Linify_brackets>\\\] { myprintstr("\\\001rbracket\003"); /* cannot have these in the way */ }
+<Linify_brackets>\]\{ { if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003\{");
+ not_OK("WHAT'S GOING ON? ]{\n");
+ print_lex_stk();
+ }
+ CHG_TOP(Linify_braces);
+ }
+<Linify_brackets>\] { if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003");
+ }
+ POP;
+ }
+
+<Index>\\\@ { MYECHO; /* my pseudo-makeindex has two magic chars */ }
+<Index>\@ { myprintstr("\001idxsort\003"); }
+<Index>\\! { MYECHO; }
+<Index>\! { myprintstr("\001idxsubitem\003"); }
+
+<Index,Linify_braces,Linify_brackets,Typing>\n {
+ lineno++;
+ lineno_fiddled++;
+ if (LEX_STK_TOP == Index) {
+ warning("I'm turning a newline inside an \\index{...} into a space\n");
+ myprintstr(" ");
+ } else if (LEX_STK_TOP == Typing) {
+ warning("I'm turning a newline inside a \\tr{...} or \\pl{...} into a space\n");
+ myprintstr(" ");
+ } else {
+ myprintstr("\001newline\003");
+ }
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>[A-Za-z0-9 \t]+ {
+ MYECHO; /* tiny efficiency */
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>. { MYECHO; /* catch all */ }
+
+<Index><<EOF>> { not_OK("unexpected end-of-file inside an \\index{...}\n");
+ exit(1);
+ }
+<Linify_braces><<EOF>> { not_OK("unexpected end-of-file inside a macro argument\n");
+ exit(1);
+ }
+<Linify_brackets><<EOF>> {not_OK("unexpected end-of-file inside a macro optional argument\n");
+ exit(1);
+ }
+<Typing><<EOF>> { not_OK("unexpected end-of-file inside a \\tr{...}\n");
+ exit(1);
+ }
+%%
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ if (argc != 5) {
+ fprintf(stderr,"Sorry, %s must have exactly 4 arguments\n", argv[0]);
+ exit(1);
+ }
+ verbose = argv[1][0] - '0'; /* hacks */
+ follow_inputs = argv[2][0] - '0';
+ lit2what = argv[3][0] - '0'; /* used in IS_LIT2xxx tests */
+ if (strcmp(argv[4], "-") == 0) {
+ yyin = stdin;
+ } else if ((yyin = fopen(argv[4], "r")) == NULL) {
+ fprintf(stderr,"%s: can't open file %s\n", argv[0], argv[4]);
+ exit(1);
+ }
+ strcpy(srcfile_name, argv[4]);
+ inputfile_stk[ inputfile_stk_top /* 0 */ ].name = argv[4];
+ if ( ! IS_LIT2PGM_Q ) printf("srcfile!_!%s!_!1!_!\n",argv[4]);
+ yylex();
+ exit(exit_status);
+}
+
+void
+push_inputfile (fname)
+char* fname;
+{
+ if ( inputfile_stk_top >= INPUTFILE_STK_SIZE ) {
+ fprintf(stderr,"\\input's too deeply nested\n");
+ exit(1);
+ }
+
+ /* record where we are in current file */
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+ inputfile_stk[ inputfile_stk_top ].handle = YY_CURRENT_BUFFER;
+ /* actual push */
+ inputfile_stk_top++;
+
+ /* open new file fname */
+ if ((yyin = fopen(fname, "r")) == NULL) {
+ fprintf(stderr,"%s:%d: can't open \\input file %s\n", srcfile_name, lineno, fname);
+ exit(1);
+ }
+ yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) );
+
+ /* report that's where we are */
+ if (! IS_LIT2PGM_Q) printf("srcfile!_!%s!_!1!_!\n",fname);
+ /* set srcfile_name and lineno for new file */
+
+ strcpy(srcfile_name, fname); /* for my own tracking */
+ lineno = 1;
+
+ /* push/record everything for new file */
+ inputfile_stk[ inputfile_stk_top ].name = srcfile_name;
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+}
+
+void
+pop_inputfile ()
+{
+ inputfile_stk_top--; /* actual pop */
+
+ /* remind where we were */
+ strcpy(srcfile_name, inputfile_stk[inputfile_stk_top].name);
+ lineno = inputfile_stk[inputfile_stk_top].lineno;
+ /* put in an extra newline or two before the next file;
+ otherwise, the cat'ting of files gives things like:
+
+ > last line of code
+ \section{Next section}
+
+ which happens to be very bad for lit2stuff.
+ */
+ if (! IS_LIT2PGM_Q) printf("\n\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+
+ /* return to prev inputfile */
+ yy_switch_to_buffer( inputfile_stk[inputfile_stk_top].handle );
+}
+
+void
+myecho ()
+{
+ myprintstr(yytext);
+}
+
+void
+myprintstr (str)
+char *str;
+{
+ if (SHLD_PRINT) {
+ printf("%s",str);
+ }
+}
+
+void
+print_leading_whitespace ()
+{
+ int i;
+
+ for (i = 0; yytext[i] == ' ' || yytext[i] == '\t'; i++) {
+ putchar(yytext[i]);
+ }
+}
+
+void
+not_OK(msg)
+char *msg;
+{
+ /* a good old emacsable error msg */
+ fprintf(stderr,"%s:%d: %s", srcfile_name, lineno, msg);
+ exit_status++;
+}
+
+void
+warning(msg) /* exit_status not fiddled */
+char *msg;
+{
+ /* a good old emacsable warning msg */
+ fprintf(stderr,"%s:%d: [warning] %s", srcfile_name, lineno, msg);
+}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-deatify.llex b/web/glasgow/lit2x-0.16/literate/lit-deatify.llex
new file mode 100644
index 0000000000..45c43efb12
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-deatify.llex
@@ -0,0 +1,669 @@
+\section[De-at-ifier]{Handles `at' and `tr' shorthands}
+
+[Taking over from lit-inputter, minus the LITINPUTS stuff]
+
+Has to know whether \tr{lit2pgm}, \tr{lit2latex} or \tr{lit2texi}
+(grabbed from deviously-passed command-line argument).
+
+And makes index entries appear well-behaved (same as \tr{\tr}, really).
+
+And nukes [most] comments (sigh).
+
+\subsection[deatify_Definitions]{Lex definitions}
+
+Here, we use \tr{lex} ``start conditions'' a lot; we keep a stack of
+them and manipulate them in a fairly obvious way. Using start
+conditions like this gives you ``mini-lexers'' within the overall
+lexer.
+\begin{code}
+%{
+#define LEX_STK_SIZE 256
+
+int lex_stk[LEX_STK_SIZE];
+int lex_stk_top = 0;
+
+#define PUSH(x) lex_stk[++lex_stk_top] = (x); BEGIN(x)
+#define POP BEGIN(lex_stk[--lex_stk_top])
+#define LEX_STK_TOP lex_stk[lex_stk_top]
+#define LEX_NEXT_TO_STK_TOP lex_stk[lex_stk_top - 1]
+#define CHG_TOP(x) lex_stk[lex_stk_top] = (x); BEGIN(x)
+#define CHG_NEXT_TO_TOP(x) lex_stk[lex_stk_top - 1] = (x)
+/* not a lot in the old stack {over,under}flow dept, what? */
+
+extern char *yytext; /* forward decl */
+void print_leading_whitespace();
+
+void
+print_lex_stk () /* just for debugging */
+{
+ int i;
+ fprintf(stderr,"lex_stk:");
+ for (i = lex_stk_top; i >= 0; i--) {
+ fprintf(stderr," %d",lex_stk[i]);
+ }
+ fprintf(stderr,"::%s\n",yytext);
+}
+\end{code}
+
+Things related to handling \tr{\input} commands (not doing this at the
+moment):
+\begin{code}
+int verbose; /* set from first argv */
+int follow_inputs; /* set from second argv */
+
+#if defined (SYSV) || defined (SYSV)
+#include <string.h>
+#include <time.h>
+#else
+#include <strings.h>
+#include <sys/time.h>
+#endif
+
+#if defined (SYSV)
+#define index(string, ch) strchr ((string), (ch))
+#endif
+
+#define INPUTFILE_STK_SIZE 20
+struct {
+ YY_BUFFER_STATE handle; /* flex-supplied magic */
+ char* name;
+ int lineno;
+} inputfile_stk[INPUTFILE_STK_SIZE];
+int inputfile_stk_top = 0;
+void push_inputfile();
+void pop_inputfile();
+int i; /* temporary */
+char* rbrace;
+\end{code}
+
+\begin{code}
+int deatify_debug = 0;
+int unmatched_lbraces = 0;
+int unmatched_lbrackets = 0;
+
+/* like everything, must track srcfile name and lineno */
+char srcfile_name[1024]; /* too lazy to do this right */
+int lineno = 1; /* count \n's as they go by */
+int lineno_fiddled = 0; /* boolean: incr if newlines get trashed */
+
+int exit_status = 0;
+void not_OK (); /* prints an error msg and bumps exit_status */
+void warning (); /* same, but no exit-status fiddling */
+
+int lit2what; /* set from ARGV */
+
+#define IS_LIT2PGM_Q (lit2what == 1)
+#define IS_LIT2PGM (lit2what == 2)
+#define IS_LIT2TEXI (lit2what == 3)
+#define IS_LIT2LATEX (lit2what == 4)
+#define IS_LIT2DEPEND (lit2what == 5)
+#define IS_LIT2CHANGELOG (lit2what== 6)
+
+/* the condition for printing to stdout */
+#define SHLD_PRINT (! IS_LIT2PGM_Q || (LEX_STK_TOP == Code || LEX_STK_TOP == Bird))
+
+void myecho();
+#define MYECHO myecho()
+void myprintstr();
+
+#define YY_USER_ACTION if (deatify_debug) print_lex_stk(); /* debugging */
+%}
+D [0-9]+
+END_WORD [-~/!\?(),\.'`A-Za-z0-9]*[ \t]*
+
+%x Norm Verb Code Bird Atting Math Index Typing Linify_braces Linify_brackets
+%%
+ CHG_TOP(Norm); /* that's where we start */
+\end{code}
+
+\subsection[deatify_Rules]{Lex rules}
+
+We start as @<Norm>@ and branch off to one of the other
+``mini-scanners'' when we see certain things.
+
+First: some magic characters absolutely verboten in the input:
+\begin{code}
+[\001\002\003] { not_OK("ASCII chars \001, \002, \003 may not appear in literate files\n");
+ exit(1);
+ }
+\end{code}
+
+
+% um... we're generating these here now...
+% (sorry, wrongo, buddy)
+First thing is the magic source-file tracking lines (only in
+\tr{<Norm>}, I think):
+\begin{code}
+<Norm>^"srcfile!_!"(.+)"!_!"([0-9]+)"!_!"\n {
+ sscanf(yytext+10,"%[^!]!_!%d", srcfile_name, &lineno);
+ if (lineno > 0) {
+ ECHO;
+ }
+ }
+\end{code}
+
+Now a bit of stuff to handle \tr{\input} lines:
+\begin{code}
+<Norm>^\\input\{[^\}\n]+\}.*\n { lineno++;
+ if (follow_inputs) {
+ /* nullify first right brace */
+ rbrace = index(yytext+7,'}');
+ *rbrace = '\0';
+ push_inputfile(yytext+7);
+ } else {
+ MYECHO;
+ }
+ }
+<Norm,Bird><<EOF>> { if ( inputfile_stk_top <= 0 ) {
+ yyterminate();
+ } else {
+ pop_inputfile();
+ }
+ CHG_TOP(Norm); /* revert */
+ }
+\end{code}
+
+
+Code and verbatim stuff gets copied through absolutely unmangled,
+using the @<Verb>@ (or almost equivalently @<Code>@) mini-scanner.
+\begin{code}
+<Norm>^\\begin\{verbatim\}.*\n |
+<Norm>^\\begin\{flushverbatim\}.*\n |
+<Norm>^\\begin\{pseudocode\}.*\n { lineno++; MYECHO; PUSH(Verb); /* some may have opt arg */ }
+<Norm>^\\begin\{code\}.*\n { lineno++;
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+ MYECHO;
+ PUSH(Code);
+ }
+\end{code}
+
+Then there's the \tr{>} business; the ugliest way ever invented for
+writing programs. You can only get there from \tr{<Norm>}, because I
+said so.
+
+\begin{code}
+<Norm>\n[ \t]+\n\> { /* convert to something less weird & try again */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Norm>\n\n\>.*\n { lineno += 3;
+ /* NB: init > converted to space */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+3);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+<Norm>\n\>.*\n { lineno++; /* so msg will have right line # */
+ if (lineno > 2) /* I feel guilty about this hack */
+ /* to avoid: file is: blank lines, then code */
+ not_OK("Bird-style code not preceded by a blank line\n");
+ lineno++; /* account for other \n */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+2);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+<Norm>^\>.*\n { lineno++; /* first line of file */
+ if (IS_LIT2PGM_Q) {
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,(lineno-1));
+ printf("%s",yytext+1);
+ } else {
+ ECHO;
+ }
+ PUSH(Bird);
+ }
+\end{code}
+
+There are a few macros (\tr{\section}, \tr{\author}, and the others
+below) that may have funny \tr{@...@}'s, etc., in them (meaning
+newlines would be inserted normally); these newlines must be
+suppressed! These macros send us off to \tr{<Linify_braces>} or
+\tr{<Linify_brackets>}, which are like \tr{<Norm>} except that the
+\tr{unput} newlines (below) get munched. (This is getting really
+horrible...)
+
+\begin{code}
+<Norm>\\author\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\caption\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\centerline\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\date\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\define\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\heading\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\label\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\menuentry\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\node\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\owner\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\[sub]*section{D}?\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\[sub]*section{D}?\[ { MYECHO; PUSH(Linify_brackets); }
+<Norm>\\standaloneornot\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\title\{ { MYECHO; PUSH(Linify_braces); }
+<Norm>\\(tr|pl)\{ { MYECHO; unmatched_lbraces = 1; PUSH(Typing);
+ /* \tr has braces as literals */
+ }
+<Norm>\\item\[ { MYECHO; PUSH(Linify_brackets); }
+\end{code}
+
+Similarly, an \tr{@} sends us off to @<Atting>@. Of course, a \tr{\@} doesn't.
+\begin{code}
+<Norm>\\@ { MYECHO; }
+<Norm>@ { myprintstr("\\codeInText{"); PUSH(Atting); }
+\end{code}
+
+Simple math mode stuff.
+
+\begin{code}
+<Norm>\\\$ { MYECHO; }
+<Norm>\$ { myprintstr("\\MathMode{"); PUSH(Math); }
+\end{code}
+
+For index commands, we want them to be at the beginning of a line (we do?);
+hence the @printf@'s here. The internal magic is done by
+@<Index>@.
+\begin{code}
+<Norm>\\index\{ { MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Index);
+ }
+\end{code}
+
+The rest of the @<Norm>@ mini-scanner handles comments and echoes
+everything else.
+\begin{code}
+<Norm>\\\{ { MYECHO; }
+<Norm>\\\} { MYECHO; }
+<Norm,Math>\\% { MYECHO; }
+<Norm,Math>\%.*\n[ \t]*\n> { /* technically this Bird-style code is wrong
+ (no blank line in front of it, but that's
+ not intuitively obvious to the casual observer).
+ Solution? A hack!
+ */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Norm,Math>\%.*\n { /* throw away */ lineno++;
+ if (! IS_LIT2PGM_Q)
+ printf("\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ }
+<Norm>[A-Za-z0-9 \t]+ { MYECHO; /* slight efficiency */ }
+<Norm>. { MYECHO; }
+<Norm>\n { /* handle line-number fiddling */
+ MYECHO;
+ lineno++;
+ if (lineno_fiddled) {
+ if (! IS_LIT2PGM_Q)
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+ lineno_fiddled = 0;
+ }
+ }
+\end{code}
+
+The \tr{<Verb>} and \tr{<Code>} mini-scanners pass everything through until it sees an
+\tr{\end <something>}. As it stands, the \tr{<something>} doesn't
+have to be what was \tr{\begun} (bug).
+\begin{code}
+<Verb>^\\end\{verbatim\} |
+<Verb>^\\end\{flushverbatim\} |
+<Verb>^\\end\{pseudocode\} { MYECHO; POP; }
+<Code>^\\end\{code\} { if (! IS_LIT2PGM_Q) ECHO; POP; }
+<Verb,Code>^[^\\\n].*\n { lineno++; MYECHO; /* a line not started by \ */}
+<Verb,Code>. { MYECHO; }
+<Verb,Code>\n { lineno++; MYECHO; }
+<Verb,Code><<EOF>> { not_OK("unexpected end-of-file in verbatim text or (pseudo)code\n");
+ exit(1);
+ }
+\end{code}
+
+The \tr{<Bird>} mini-scanner is here only to check for
+no-blank-line-after errors in uglyly-written code.
+\begin{code}
+<Bird>[ \t\n]*\n\>.*\n? { /* whitespace/blank-lines do not matter */
+ /* count lines... */
+ for (i = 0; i < strlen(yytext); i++) {
+ if (yytext[i] == '\n')
+ lineno++;
+ }
+ if (! IS_LIT2PGM_Q) {
+ ECHO;
+ } else { /* don't print leading whitestuff */
+ for (i = 0; i < strlen(yytext) && yytext[i] != '>'; i++)
+ ; /* no-op */
+ /* report where this got us...*/
+ printf("srcfile!_!%s!_!%d!_!\n",srcfile_name,
+ ((yytext[yyleng-1] == '\n') ? (lineno-1) : lineno));
+ /* putchar(' '); convert leading > to space */
+ for ( i++ ; i < strlen(yytext); i++)
+ putchar(yytext[i]);
+ }
+ }
+<Bird>^\>.*\n? { if (yytext[yyleng-1] == '\n') { lineno++; }
+ if (IS_LIT2PGM_Q) printf("%s",yytext+1); else ECHO;
+ }
+<Bird>[ \t]*\n { lineno++;
+ if ( ! IS_LIT2PGM_Q) ECHO;
+ POP;
+ }
+<Bird>. { lineno--; /* to get right # on msg */
+ not_OK("Bird-style code not followed by a blank line\n");
+ lineno++; /* put it back */
+ unput(yytext[0]);
+ POP;
+ }
+\end{code}
+
+\tr{<Typing>} and \tr{<Index>} deal with braces the same way: these
+rules must come before the default rules for \tr{<Typing>.} and
+\tr{<Index>.}.
+
+The rule of the @<Atting>@ game is to send everything through except
+right braces and newlines (which break the use of @/[^\}]+/@ regexps).
+No longer worry about one per line.
+
+\begin{code}
+<Atting>@@ { myprintstr("@"); }
+<Atting>@\\noindex\{\} |
+<Atting>@\\noindex { myprintstr("\001noindex\003}");
+ POP;
+ }
+<Atting>@ { myprintstr("}");
+ POP;
+ }
+<Atting>\{ { myprintstr("\001lbrace\003"); }
+<Atting>\} { myprintstr("\001rbrace\003"); }
+<Atting>\n { warning("I'm turning a newline inside a @...@ into a space\n");
+ myprintstr(" ");
+ lineno++;
+ }
+
+<Atting><<EOF>> { not_OK("unexpected end-of-file inside an @ ... @\n");
+ exit(1);
+ }
+<Atting>[A-Za-z0-9 \t]+ { MYECHO; /* tiny efficiency */ }
+<Atting>. { MYECHO; }
+\end{code}
+
+Math mode stuff. At present, only extra work is to replace some
+control sequences with plain text---for \tr{lit2texi} only.
+
+\begin{code}
+<Math>\\\$ { MYECHO; }
+<Math>\$ { myprintstr("}");
+ POP;
+ }
+<Math>\{ { myprintstr("\001lbrace\003"); }
+<Math>\} { myprintstr("\001rbrace\003"); }
+<Math>\n { myprintstr("\001newline\003");
+ lineno++;
+ }
+
+<Math><<EOF>> { not_OK("unexpected end-of-file inside $ ... $ (math mode)\n");
+ exit(1);
+ }
+<Math>[A-Za-z0-9 \t]+ { MYECHO; /* tiny efficiency */ }
+<Math>. { MYECHO; }
+\end{code}
+
+The braces/brackets stuff isn't too bad. Well, there's the stuff for
+\tr{\tr} and \tr{@..@}'s (no \tr{\index}'s now...) ...
+\begin{code}
+<Linify_braces,Linify_brackets>\\(tr|pl)\{ {
+ MYECHO;
+ unmatched_lbraces = 1;
+ PUSH(Typing);
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\\\ {
+ MYECHO;
+ }
+<Index,Linify_braces,Linify_brackets,Typing>\\ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\\\{ {
+ MYECHO;
+ }
+
+<Linify_braces>\{ { MYECHO; PUSH(Linify_braces); }
+<Linify_brackets>\{ { MYECHO; }
+
+<Index,Typing>\{ { unmatched_lbraces++; myprintstr("\001lbrace\003"); }
+
+<Linify_braces,Linify_brackets>\\\} {
+ MYECHO;
+ }
+<Linify_braces>\}\{ { /* next arg */ MYECHO; }
+
+<Linify_braces>\} { MYECHO; POP; }
+<Linify_brackets>\} { MYECHO; }
+
+<Index,Typing>\} { if (--unmatched_lbraces == 0) {
+ MYECHO;
+ POP;
+ } else {
+ myprintstr("\001rbrace\003");
+ }
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\@ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>@ {
+ myprintstr("\\codeInText{"); /* no newline */
+ PUSH(Atting);
+ }
+<Typing>@ { MYECHO; /* NB: magic <Index> chars below */ }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\\$ {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\$ {
+ myprintstr("\\MathMode{"); /* no newline */
+ PUSH(Math);
+ }
+<Index,Typing>\$ { MYECHO; }
+
+<Index,Linify_braces,Linify_brackets,Typing>\\% {
+ MYECHO;
+ }
+<Linify_braces,Linify_brackets>\%.*\n[ \t]*\n> {
+ /* see earlier comments about crimes against humanity */
+ unput('>'); unput('\n'); unput('\n');
+ }
+<Linify_braces,Linify_brackets>\%.*\n { /* throw away */
+ lineno++;
+ lineno_fiddled++;
+ }
+<Index,Typing>% { MYECHO; }
+
+<Linify_brackets>\\\[ { MYECHO; }
+<Linify_brackets>\[ { MYECHO; PUSH(Linify_brackets); }
+
+<Linify_brackets>\\\] { myprintstr("\\\001rbracket\003"); /* cannot have these in the way */ }
+<Linify_brackets>\]\{ { if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003\{");
+ not_OK("WHAT'S GOING ON? ]{\n");
+ print_lex_stk();
+ }
+ CHG_TOP(Linify_braces);
+ }
+<Linify_brackets>\] { if (LEX_NEXT_TO_STK_TOP == Norm) {
+ MYECHO;
+ } else {
+ myprintstr("\001rbracket\003");
+ }
+ POP;
+ }
+
+<Index>\\\@ { MYECHO; /* my pseudo-makeindex has two magic chars */ }
+<Index>\@ { myprintstr("\001idxsort\003"); }
+<Index>\\! { MYECHO; }
+<Index>\! { myprintstr("\001idxsubitem\003"); }
+
+<Index,Linify_braces,Linify_brackets,Typing>\n {
+ lineno++;
+ lineno_fiddled++;
+ if (LEX_STK_TOP == Index) {
+ warning("I'm turning a newline inside an \\index{...} into a space\n");
+ myprintstr(" ");
+ } else if (LEX_STK_TOP == Typing) {
+ warning("I'm turning a newline inside a \\tr{...} or \\pl{...} into a space\n");
+ myprintstr(" ");
+ } else {
+ myprintstr("\001newline\003");
+ }
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>[A-Za-z0-9 \t]+ {
+ MYECHO; /* tiny efficiency */
+ }
+
+<Index,Linify_braces,Linify_brackets,Typing>. { MYECHO; /* catch all */ }
+
+<Index><<EOF>> { not_OK("unexpected end-of-file inside an \\index{...}\n");
+ exit(1);
+ }
+<Linify_braces><<EOF>> { not_OK("unexpected end-of-file inside a macro argument\n");
+ exit(1);
+ }
+<Linify_brackets><<EOF>> {not_OK("unexpected end-of-file inside a macro optional argument\n");
+ exit(1);
+ }
+<Typing><<EOF>> { not_OK("unexpected end-of-file inside a \\tr{...}\n");
+ exit(1);
+ }
+\end{code}
+
+Finally, we have a non-default @main@ routine because we need to pick
+up the (mandatory) argument that says if we're doing pre-processing
+for \tr{lit2pgm}, \tr{lit2latex}, or \tr{lit2texi}.
+\begin{code}
+%%
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ if (argc != 5) {
+ fprintf(stderr,"Sorry, %s must have exactly 4 arguments\n", argv[0]);
+ exit(1);
+ }
+ verbose = argv[1][0] - '0'; /* hacks */
+ follow_inputs = argv[2][0] - '0';
+ lit2what = argv[3][0] - '0'; /* used in IS_LIT2xxx tests */
+ if (strcmp(argv[4], "-") == 0) {
+ yyin = stdin;
+ } else if ((yyin = fopen(argv[4], "r")) == NULL) {
+ fprintf(stderr,"%s: can't open file %s\n", argv[0], argv[4]);
+ exit(1);
+ }
+ strcpy(srcfile_name, argv[4]);
+ inputfile_stk[ inputfile_stk_top /* 0 */ ].name = argv[4];
+ if ( ! IS_LIT2PGM_Q ) printf("srcfile!_!%s!_!1!_!\n",argv[4]);
+ yylex();
+ exit(exit_status);
+}
+
+void
+push_inputfile (fname)
+char* fname;
+{
+ if ( inputfile_stk_top >= INPUTFILE_STK_SIZE ) {
+ fprintf(stderr,"\\input's too deeply nested\n");
+ exit(1);
+ }
+
+ /* record where we are in current file */
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+ inputfile_stk[ inputfile_stk_top ].handle = YY_CURRENT_BUFFER;
+ /* actual push */
+ inputfile_stk_top++;
+
+ /* open new file fname */
+ if ((yyin = fopen(fname, "r")) == NULL) {
+ fprintf(stderr,"%s:%d: can't open \\input file %s\n", srcfile_name, lineno, fname);
+ exit(1);
+ }
+ yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) );
+
+ /* report that's where we are */
+ if (! IS_LIT2PGM_Q) printf("srcfile!_!%s!_!1!_!\n",fname);
+ /* set srcfile_name and lineno for new file */
+
+ strcpy(srcfile_name, fname); /* for my own tracking */
+ lineno = 1;
+
+ /* push/record everything for new file */
+ inputfile_stk[ inputfile_stk_top ].name = srcfile_name;
+ inputfile_stk[ inputfile_stk_top ].lineno = lineno;
+}
+
+void
+pop_inputfile ()
+{
+ inputfile_stk_top--; /* actual pop */
+
+ /* remind where we were */
+ strcpy(srcfile_name, inputfile_stk[inputfile_stk_top].name);
+ lineno = inputfile_stk[inputfile_stk_top].lineno;
+ /* put in an extra newline or two before the next file;
+ otherwise, the cat'ting of files gives things like:
+
+ > last line of code
+ \section{Next section}
+
+ which happens to be very bad for lit2stuff.
+ */
+ if (! IS_LIT2PGM_Q) printf("\n\nsrcfile!_!%s!_!%d!_!\n",srcfile_name,lineno);
+
+ /* return to prev inputfile */
+ yy_switch_to_buffer( inputfile_stk[inputfile_stk_top].handle );
+}
+
+void
+myecho ()
+{
+ myprintstr(yytext);
+}
+
+void
+myprintstr (str)
+char *str;
+{
+ if (SHLD_PRINT) {
+ printf("%s",str);
+ }
+}
+
+void
+print_leading_whitespace ()
+{
+ int i;
+
+ for (i = 0; yytext[i] == ' ' || yytext[i] == '\t'; i++) {
+ putchar(yytext[i]);
+ }
+}
+
+void
+not_OK(msg)
+char *msg;
+{
+ /* a good old emacsable error msg */
+ fprintf(stderr,"%s:%d: %s", srcfile_name, lineno, msg);
+ exit_status++;
+}
+
+void
+warning(msg) /* exit_status not fiddled */
+char *msg;
+{
+ /* a good old emacsable warning msg */
+ fprintf(stderr,"%s:%d: [warning] %s", srcfile_name, lineno, msg);
+}
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-globals.lprl b/web/glasgow/lit2x-0.16/literate/lit-globals.lprl
new file mode 100644
index 0000000000..3ab4edde1b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-globals.lprl
@@ -0,0 +1,381 @@
+\section[Global_data]{Global data structures for processing}
+
+The main stuff is kept in global structures; to improve quality of
+life, global things' names start with Capital Letters. If it ain't
+described here, it ain't supposed to be global! (Well, except for
+some command-line option variables...)
+
+The document being processed is taken to be a sequence of {\em
+sections}\index{sections}, each made of zero or more {\em
+blocks}\index{blocks} (see next section) of stuff-of-one-kind. Important:
+whereas the ``sections'' the user sees may be nested within each other
+(e.g., sections within a chapter), a ``section'' here just the
+sequence of blocks between one sectioning command (\tr{\section<n>})
+and the next (\tr{\section<m>}, for any \tr{<n>} and \tr{<m>}. For
+example, the stuff before the first sectioning command is the root
+``section'' (number~0.0.0...), the stuff between (e.g.) a
+\tr{\section1} command and an ensuing \tr{\section2} command is a
+``section,'' etc. Confusing, but only to us hackers...
+
+\subsection[Data_about_sections]{Global data about sections}
+
+\begin{code}
+&init_section_data_structures();
+
+sub init_section_data_structures { # also used in the linker
+\end{code}
+
+Things we want to keep track of about ``sections'' (values for the root
+section are provided):
+\begin{description}
+\item[@Sec_depth@:]
+the sectioning depth provided by the user; 0 is a special depth only
+for the root section (pre-amble) [sparked by seeing
+\tr{\documentstyle}] and the \tr{\end{document}} section; -1 means no
+depth has been assigned.
+\begin{code}
+ @Sec_depth = (-1);
+\end{code}
+
+\item[@Sec_abs_depth@:]
+the absolute sectioning depth; it is calculated.
+\begin{code}
+ @Sec_abs_depth = (-1);
+\end{code}
+
+\item[@Sec_nodename@:]
+the default node-name for that section; to go from a
+nodename to a section number, we have the auxiliary associative array
+@%Nodename_sec@. The array @Sec_alias@ contains {\em extra}
+names for this section, introduced by \tr{\label}s.
+\begin{code}
+ @Sec_nodename = (''); # 'Top' (set by \documentstyle)
+ %Nodename_sec = (); # ('Top', 0);
+ @Sec_aliases = ('');
+\end{code}
+
+\item[@Sec_nodespec@:]
+a specification (a string) for how each node is wired up (\tr{lit2texi}).
+\begin{code}
+ @Sec_nodespec = (''); # Top,,,(dir)
+\end{code}
+
+\item[@Sec_title@]
+gives the text of the title for a
+section.
+\begin{code}
+ @Sec_title = ('');
+\end{code}
+
+\item[@Sec_numstr@:]
+the section number as a string,
+full-stop/period-separated; the associative array @%Sec_numstr_exists@
+(indexed by @Sec_numstr@'s) is used to help find (e.g.) a
+\tr{\section<n>}'s \tr{\section<n+1>}'s, and such like.
+@Sec_vec@, a sort-of counter, is very much related; in turn, the routine
+@incr_Sec_vec@ is very much related to it.
+\begin{code}
+ @Sec_numstr = (''); # (0.0.0.0.0.0.0.0.0.0.0.0')
+ %Sec_numstr_exists = (); # ('0.0.0.0.0.0.0.0.0.0.0.0', 0)
+
+ # 12 sectioning levels for the user; level 0 is magic and extra
+ # that -1 will be bumped first thing (we hope)
+ @Sec_vec = (-1,0,0,0,0,0,0,0,0,0,0,0,0); # curr Sec_numstr in non-string form
+\end{code}
+
+\item[@Sec_first_blk@ and @Sec_last_blk@:]
+these point the way to a section's blocks (see next section).
+\begin{code}
+ @Sec_first_blk = (0); # to find their blocks
+ @Sec_last_blk = (-1);
+\end{code}
+
+\item[@Sec_owner@:]
+who should be listed as the owner of this section when a \tr{-O} flag
+given; set from \tr{\owner} command; otherwise, from who actually owns
+the source-file of the section's first block.
+\begin{code}
+ @Sec_owner = ('');
+\end{code}
+
+\item[@Sec_extra_menu_entries@:]
+a string giving extra menu entries (from user's \tr{\menuentry}
+requests).
+\begin{code}
+ @Sec_extra_menu_entries = ('');
+\end{code}
+
+\item[@Sec_codethings_defd@ and @Sec_codethings_used@:]
+a comma-separated string of ``interesting'' things found by
+@find_interesting_codethings@ in this section.
+
+\begin{code}
+ @Sec_codethings_defd = ('');
+ @Sec_codethings_used = ('');
+ %Codething_defd_sec = (); # only used in the linker
+
+} # end of subroutine init_section_data_structures
+\end{code}
+\end{description}
+
+\begin{code}
+sub tidy_numstr {
+ local($numstr) = @_;
+
+ $numstr =~ s/^-1\.//; # strip leading -1 (I don't like this...)
+ $numstr =~ s/^[0\.]+\.//; # strip leading zeros
+ $numstr =~ s/\.[0\.]+$//; # strip trailing zeros
+ $numstr;
+}
+
+$S = 0; # reserved scalar for walking through sections
+
+# constants; full LaTeX hierarchy
+# all subparagraphs (LaTeX) or subsubsections (Texinfo) below
+# a certain level -- for now
+$MAX_SEC_DEPTH = 12;
+
+sub incr_Sec_vec {
+ local($i) = @_; # the section-depth to increment
+
+# print STDERR "entering incr_Sec_vec: $i\n" if $Debugging;
+
+ $Sec_vec[$i] = $Sec_vec[$i] + 1;
+ $i++;
+ while ($i <= $#Sec_vec) { # zero out subsections
+ $Sec_vec[$i] = 0;
+ $i++;
+ }
+}
+
+#operations on Secs
+
+sub start_new_section { # wind up curr section, make ready for next
+
+# print STDERR "entering start_new_section\n" if $Debugging;
+
+ $S++;
+ if (! &empty_blk_p($B)) {
+ $Sec_last_blk[$S - 1] = $B;
+ &incr_blk_ctr(); # new section -> new block
+ } else {
+ $Sec_last_blk[$S - 1] = $B - 1;
+ $Blk_sec[$B] = $S;
+ }
+
+ $Sec_depth[$S] = -1; # means: unknown"
+ $Sec_abs_depth[$S] = -1;
+ $Sec_nodename[$S] = '';
+ $Sec_aliases[$S] = '';
+ $Sec_nodespec[$S] = '';
+ $Sec_title[$S] = '';
+ $Sec_numstr[$S] = '';
+ $Sec_first_blk[$S] = $B;
+ $Sec_last_blk[$S] = -1;
+
+ $Sec_owner[$S] = '';
+ $Sec_extra_menu_entries[$S] = '';
+ $Sec_codethings_defd[$S] = '';
+ $Sec_codethings_used[$S] = '';
+}
+
+\end{code}
+
+\subsection[Data_about_blocks]{Global data about blocks}
+
+Each ``section'' is a sequence of ``blocks'' of stuff: each block
+has a type (text, code, etc.) and some text, plus some other
+miscellaneous information. The presumption is that, though blocks may
+change internally (number of lines, etc.), the number/order/etc.~of
+blocks won't change.
+
+\begin{code}
+@Blk_type = ('');
+@Blk_sec = (''); # backpointer to what section it's in
+@Blk_magic = (''); # mainly ribbon names, for "code"
+@Blk_txt = ('');
+@Blk_srcfile_name = ('');
+@Blk_srcfile_lineno = (1);
+
+# list of codethings defined/used in this block (if code)
+@Blk_codethings_defd = ();
+@Blk_codethings_used = ();
+
+$B = 0; # reserved for walking through blocks
+
+# operations thereon
+
+sub empty_blk_p { # empty if it has no text
+ local($blk_no) = @_;
+
+ ($Blk_txt[$B] eq '') ? 1 : 0;
+}
+
+sub incr_blk_ctr {
+# print STDERR "entering incr_blk_ctr\n" if $Debugging;
+
+ $B++;
+ $Blk_type[$B] = '';
+ $Blk_sec[$B] = $S; # that's where we are
+ $Blk_txt[$B] = '';
+ $Blk_magic[$B] = '';
+ $Blk_srcfile_name[$B] = '';
+ $Blk_srcfile_lineno[$B] = -1;
+ $Blk_codethings_defd[$B]= '';
+ $Blk_codethings_used[$B]= '';
+}
+
+sub set_blk_magic_info { # for special info about specific types of blks
+ local($b_info) = @_;
+
+ $Blk_magic[$B] = $b_info;
+}
+
+sub append_to_curr_blk {
+ local($b_type, $b_txt) = @_;
+
+ if (&empty_blk_p($B)) { # first use
+ &not_OK($Srcfile_name, $Srcfile_lineno, # I hope that's right...
+ "non-matching type on empty blk with type already set\n")
+ if ($Blk_type[$B] && $Blk_type[$B] ne $b_type);
+
+ $Blk_type[$B] = $b_type;
+ $Blk_txt[$B] = $b_txt;
+ $Blk_srcfile_name[$B] = $Srcfile_name;
+ $Blk_srcfile_lineno[$B] = $Srcfile_lineno;
+
+ } elsif ($Blk_type[$B] ne $b_type) { # ???
+ &not_OK($Srcfile_name, $Srcfile_lineno, # I hope that's right...
+ "unexpected blk type change in append_to_curr_blk: $Blk_type[$B], $b_type; $b_txt\n");
+ $Blk_type[$B] = $b_type;
+ $Blk_txt[$B] = $b_txt;
+ $Blk_srcfile_name[$B] = $Srcfile_name;
+ $Blk_srcfile_lineno[$B] = $Srcfile_lineno;
+
+ } else {
+ $Blk_txt[$B] .= $b_txt;
+ }
+}
+\end{code}
+
+Executable/compilable code (inside \tr{\begin{code} ... \end{code}}) is
+associated with one or more code {\em ribbons}; by default, code is
+appended onto ribbon \tr{main}. During @read_and_categorize_input@, the
+numbers for all the blocks holding code for ribbon \tr{foo} are
+accumulated into @$Ribbon_blks{'foo'}@.
+
+\begin{code}
+%Ribbon_blks = ();
+\end{code}
+
+\subsection[Other_global_data]{Other global data}
+
+Miscellaneous global things.
+
+\begin{code}
+$Srcfile_name = ''; # source file current line came from
+$Srcfile_lineno = 0; # line number of current line
+
+$Doc_title = '';
+$Doc_author = '';
+$Doc_date = '';
+
+$Only_latex = 0;
+$Only_info = 0;
+
+# for \define{<foo>}{<bar>} things; some built-in for lit2texi
+%Define = ();
+if ($Lit2texi) {
+ $Define{'LaTeX'} = 'LaTeX';
+ $Define{'Haskell'} = 'Haskell';
+ $Define{'TeX'} = 'TeX';
+ $Define{'ldots'} = '...';
+}
+
+%SECCMD_DEPTH = ('RESERVED_A_bug_if_you_see_it', 0,
+ 'part', 1, 'chapter', 2, 'section', 3,
+ 'subsection', 4, 'subsubsection', 5, 'paragraph', 6,
+ 'subparagraph', 7,'subparagraph', 8, 'subparagraph', 9,
+ 'subparagraph',10,'subparagraph', 11, 'subparagraph', 12
+ );
+# LaTeX (used for \section(ref|type)s for Texinfo as well)
+@SECDEPTH_LCMD =('RESERVED_A_bug_if_you_see_it',
+ 'part', 'chapter', 'section',
+ 'subsection', 'subsubsection', 'paragraph',
+ 'subparagraph','subparagraph', 'subparagraph',
+ 'subparagraph','subparagraph', 'subparagraph'
+ );
+# Texinfo -- really need something like 'part'
+@SECDEPTH_TCMD =('RESERVED_A_bug_if_you_see_it',
+ 'chapter', 'chapter', 'section',
+ 'subsection', 'subsubsection', 'subsubsection',
+ 'subsubsection','subsubsection','subsubsection',
+ 'subsubsection','subsubsection','subsubsection'
+ );
+
+# a table of \begin/end environments we known what to do with
+# this is so lit2texi can turn the others into something sensible
+$KNOWN_ENV{'change'} = 1;
+$KNOWN_ENV{'comment'} = 1;
+$KNOWN_ENV{'description'} = 1;
+$KNOWN_ENV{'display'} = 1;
+$KNOWN_ENV{'document'} = 1;
+$KNOWN_ENV{'enumerate'} = 1;
+$KNOWN_ENV{'figure'} = 1;
+$KNOWN_ENV{'flushdisplay'} = 1;
+$KNOWN_ENV{'flushverbatim'} = 1;
+$KNOWN_ENV{'itemise'} = 1;
+$KNOWN_ENV{'itemize'} = 1;
+$KNOWN_ENV{'menu'} = 1;
+# onlylatex/info/etc should never get far enough to be seen
+# so they aren't in this table.
+$KNOWN_ENV{'quotation'} = 1;
+$KNOWN_ENV{'table'} = 1;
+$KNOWN_ENV{'tabular'} = 1;
+$KNOWN_ENV{'test'} = 1;
+$KNOWN_ENV{'verbatim'} = 1;
+\end{code}
+
+\subsection[Debugging_global_data]{Debugging global data}
+
+\begin{code}
+sub dump_sections_and_blocks {
+ local(@ln, $l); # for blk text lines
+ local($temp);
+
+# print STDERR "entering dump_sections_and_blocks\n" if $Debugging;
+# this may not be printing the latest and greatest stuff
+
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) {
+ print STDERR "Section $S ($Sec_numstr[$S]):: depth: $Sec_depth[$S]; abs_depth: $Sec_abs_depth[$S]; nodename: $Sec_nodename[$S]; nodespec: $Sec_nodespec[$S]; blks: $Sec_first_blk[$S]:$Sec_last_blk[$S]; title: $Sec_title[$S]\n";
+ foreach ($B = $Sec_first_blk[$S]; $B <= $Sec_last_blk[$S]; $B++) {
+ print STDERR " Block $B; sec $Blk_sec[$B]; srcfile: $Blk_srcfile_name[$B]/$Blk_srcfile_lineno[$B]; type: $Blk_type[$B]; magic: $Blk_magic[$B]\n";
+
+ &not_OK($Blk_srcfile_name[$B], $Blk_srcfile_lineno[$B],
+ "!!! Hey blk_sec ne sec: $Blk_sec[$B] != $S\n") if $Blk_sec[$B] != $S;
+ $temp = $Blk_txt[$B];
+ $temp =~ s/\n/\\n\n/g;
+ @ln = split(/\n/,$temp);
+ for $l (@ln) {
+ print STDERR "\t$l\n";
+ }
+ if ($Blk_type[$B] eq 'code') {
+ print STDERR "codethings defd: $Blk_codethings_defd[$B]\n"
+ if $Blk_codethings_defd[$B];
+ print STDERR "codethings used: $Blk_codethings_used[$B]\n"
+ if $Blk_codethings_used[$B];
+ }
+ }
+ print STDERR "sec codethings defd: $Sec_codethings_defd[$S]\n"
+ if $Sec_codethings_defd[$S];
+ print STDERR "sec codethings used: $Sec_codethings_used[$S]\n"
+ if $Sec_codethings_used[$S];
+ print STDERR "\n";
+ }
+ print STDERR "Ribbons:\n";
+ local($ribbon,$blk_list);
+ while (($ribbon, $blk_list) = each %Ribbon_blks) {
+ print STDERR "\t$ribbon: $blk_list\n";
+ }
+}
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-inputter.lprl b/web/glasgow/lit2x-0.16/literate/lit-inputter.lprl
new file mode 100644
index 0000000000..fac6ecd3db
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-inputter.lprl
@@ -0,0 +1,121 @@
+\section[Inputter]{Read files, follow \tr{\input}'s, do definitions}
+
+At the beginning and end of each \tr{\input}'d file, the source file
+name and line number is reported, in lines of the form (separate for
+reasons of C-hacking convenience):
+% first space makes it invisible to itself
+\begin{verbatim}
+ srcfile!_!filename!_!line-number!_!
+\end{verbatim}
+
+At this point, I expect the filename specified in the
+\tr{\input} to be exactly the desired name (no implied suffix,
+etc.), somewhere along the \tr{LITINPUTS} path (specified by that
+environment variable).
+
+\begin{code}
+($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/;
+$Verbose = shift(@ARGV); # they had better be there!
+$Follow_inputs = shift(@ARGV);
+$Litinputs = shift(@ARGV);
+@Litinput = split(/:/,$Litinputs);
+$Exit_status = 0; # everything OK
+
+# read STDIN ("-") if no files specified
+#
+unshift(@ARGV, '-') if $#ARGV < $[;
+while ($ARGV = shift) {
+ &send_file($ARGV, 'fh00');
+}
+exit $Exit_status;
+
+sub send_file { # follows an example in the `open' item in perl man page
+
+ local($fname,$fhandle) = @_;
+ local($l_no) = 1;
+ local($follow_file);
+ $fhandle++; # a string increment
+
+ local($last_seen_dir) = $fname;
+ $last_seen_dir =~ s/\/[^\/]+$//; # strip to dir name
+ $last_seen_dir = '.' if ($last_seen_dir eq $fname);
+
+ unless (open($fhandle, $fname)) {
+ print STDERR "$Pgm: Can't open $fname: $!\n";
+ $Exit_status++;
+ return;
+ }
+
+ local($is_intermed_file) = ($fname =~ /\.(itxi|itex)$/) ? 1 : 0;
+
+ while (<$fhandle>) {
+ if ($l_no == 1 && ! $is_intermed_file) { # beginning
+ print "srcfile!_!$fname!_!1!_!\n";
+ }
+
+ # we do *nothing* to rawlatex environments
+ if ( /^\\begin\{rawlatex\}/ || /\001beginrawlatex\003/ ) {
+ while ($_ ne '' && ! (/^\\end\{rawlatex\}/ || /\001endrawlatex\003/ )) {
+ print $_;
+ $_ = <$fhandle>;
+ }
+ }
+
+ if (/^\\inputnow\{(.*)\}\s*(%.*)?$/ # dubious ...
+ || ($Follow_inputs
+ && (/^\\input\s*\{(.*)\}\s*(%.*)?$/
+ || /^\@input\s*\{(.*\.itxi)\}\s*$/))) {
+ $follow_file = &find_on_Litinputs($1, $last_seen_dir);
+
+ if ($follow_file) { # it found something
+ print STDERR "reading $follow_file ...\n" if $Verbose;
+ &send_file($follow_file,$fhandle);
+ # add a couple of blank lines in case
+ # the last thing was some Miranda-style code
+ print "\n\n\n";
+ print "srcfile!_!$fname!_!".($l_no+1)."!_!\n" if ! $is_intermed_file;
+ } else {
+ print STDERR "$fname:$l_no: Couldn't handle: $_";
+ $Exit_status++;
+ }
+ } else {
+ print $_;
+ }
+ } continue { $l_no++; }
+ close($fhandle);
+}
+
+sub find_on_Litinputs {
+ local($name, $last_seen_dir) = @_;
+ local($lit);
+
+ if ($name =~ /^\//) { # absolute pathname
+ print STDERR "trying $name...\n" if $Verbose;
+ if (-f $name) { # exists
+ return($name);
+ } else {
+ print STDERR " file `$name' doesn't exist\n";
+ $Exit_status++;
+ return('');
+ }
+ } else { # hop along $Litinputs
+ foreach $lit (@Litinput) {
+ # handle . magically
+ if ($lit eq '.') { # SPECIAL try for a file in last_seen_dir
+
+ print STDERR "trying $last_seen_dir/$name...\n" if $Verbose;
+ if (-f "$last_seen_dir/$name") {
+ return("$last_seen_dir/$name");
+ }
+ }
+ print STDERR "trying $lit/$name...\n" if $Verbose;
+ if (-f "$lit/$name") {
+ return("$lit/$name");
+ }
+ }
+ $Exit_status++;
+ print STDERR "No file `$name' along LITINPUTS path `$Litinputs'\n";
+ return (''); # sigh
+ }
+}
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-inputter.prl b/web/glasgow/lit2x-0.16/literate/lit-inputter.prl
new file mode 100644
index 0000000000..9f3e1deca0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-inputter.prl
@@ -0,0 +1,104 @@
+($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/;
+$Verbose = shift(@ARGV); # they had better be there!
+$Follow_inputs = shift(@ARGV);
+$Litinputs = shift(@ARGV);
+@Litinput = split(/:/,$Litinputs);
+$Exit_status = 0; # everything OK
+
+# read STDIN ("-") if no files specified
+#
+unshift(@ARGV, '-') if $#ARGV < $[;
+while ($ARGV = shift) {
+ &send_file($ARGV, 'fh00');
+}
+exit $Exit_status;
+
+sub send_file { # follows an example in the `open' item in perl man page
+
+ local($fname,$fhandle) = @_;
+ local($l_no) = 1;
+ local($follow_file);
+ $fhandle++; # a string increment
+
+ local($last_seen_dir) = $fname;
+ $last_seen_dir =~ s/\/[^\/]+$//; # strip to dir name
+ $last_seen_dir = '.' if ($last_seen_dir eq $fname);
+
+ unless (open($fhandle, $fname)) {
+ print STDERR "$Pgm: Can't open $fname: $!\n";
+ $Exit_status++;
+ return;
+ }
+
+ local($is_intermed_file) = ($fname =~ /\.(itxi|itex)$/) ? 1 : 0;
+
+ while (<$fhandle>) {
+ if ($l_no == 1 && ! $is_intermed_file) { # beginning
+ print "srcfile!_!$fname!_!1!_!\n";
+ }
+
+ # we do *nothing* to rawlatex environments
+ if ( /^\\begin\{rawlatex\}/ || /\001beginrawlatex\003/ ) {
+ while ($_ ne '' && ! (/^\\end\{rawlatex\}/ || /\001endrawlatex\003/ )) {
+ print $_;
+ $_ = <$fhandle>;
+ }
+ }
+
+ if (/^\\inputnow\{(.*)\}\s*(%.*)?$/ # dubious ...
+ || ($Follow_inputs
+ && (/^\\input\s*\{(.*)\}\s*(%.*)?$/
+ || /^\@input\s*\{(.*\.itxi)\}\s*$/))) {
+ $follow_file = &find_on_Litinputs($1, $last_seen_dir);
+
+ if ($follow_file) { # it found something
+ print STDERR "reading $follow_file ...\n" if $Verbose;
+ &send_file($follow_file,$fhandle);
+ # add a couple of blank lines in case
+ # the last thing was some Miranda-style code
+ print "\n\n\n";
+ print "srcfile!_!$fname!_!".($l_no+1)."!_!\n" if ! $is_intermed_file;
+ } else {
+ print STDERR "$fname:$l_no: Couldn't handle: $_";
+ $Exit_status++;
+ }
+ } else {
+ print $_;
+ }
+ } continue { $l_no++; }
+ close($fhandle);
+}
+
+sub find_on_Litinputs {
+ local($name, $last_seen_dir) = @_;
+ local($lit);
+
+ if ($name =~ /^\//) { # absolute pathname
+ print STDERR "trying $name...\n" if $Verbose;
+ if (-f $name) { # exists
+ return($name);
+ } else {
+ print STDERR " file `$name' doesn't exist\n";
+ $Exit_status++;
+ return('');
+ }
+ } else { # hop along $Litinputs
+ foreach $lit (@Litinput) {
+ # handle . magically
+ if ($lit eq '.') { # SPECIAL try for a file in last_seen_dir
+
+ print STDERR "trying $last_seen_dir/$name...\n" if $Verbose;
+ if (-f "$last_seen_dir/$name") {
+ return("$last_seen_dir/$name");
+ }
+ }
+ print STDERR "trying $lit/$name...\n" if $Verbose;
+ if (-f "$lit/$name") {
+ return("$lit/$name");
+ }
+ }
+ $Exit_status++;
+ print STDERR "No file `$name' along LITINPUTS path `$Litinputs'\n";
+ return (''); # sigh
+ }
+}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-link-globals.lprl b/web/glasgow/lit2x-0.16/literate/lit-link-globals.lprl
new file mode 100644
index 0000000000..eb081d8fef
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-link-globals.lprl
@@ -0,0 +1,9 @@
+\section[Link_globals]{Global data needed only for linking}
+
+\begin{code}
+$Base_sec_depth = 0; # changed by \{up,down}section commands
+$Sec_depth_offset=1; # changed by \documentstyle, \rootsectiontype commands
+
+# a trailing 1 seems to be the habit for inc'd perl files
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-linker.lprl b/web/glasgow/lit2x-0.16/literate/lit-linker.lprl
new file mode 100644
index 0000000000..b9ee25a1ce
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-linker.lprl
@@ -0,0 +1,525 @@
+\begin{code}
+sub first_link_pass { # just collecting information
+ &init_section_data_structures();
+ $S = -1; # section counter; should be bumped before use!!!
+
+ $pipe_string = "$Lit_inputter $Verbose 1 $Litinputs $Input_file";
+ print STDERR "link(1):in=$pipe_string\n" if $Verbose;
+ print STDERR " out=/dev/null\n" if $Verbose;
+ # NB: not supposed to have any output...
+ &do_std_opens($pipe_string,'/dev/null');
+
+ while (<INPIPE>) {
+ if (/^\001(down|up)section\003$/) {
+ $Base_sec_depth++ if $1 eq 'down';
+ $Base_sec_depth-- if $1 eq 'up';
+
+ } elsif (/^\001rootsectiontype\003(\d+)\002$/) {
+ $Sec_depth_offset = $1;
+
+ } elsif (/^\001section\003(.+)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)/) {
+ local($sec_depth) = $1;
+ local($nodename) = $2;
+ local($nodespec) = $3;
+ local($owner) = $4;
+ local($xtra_menu) = &deatified2verb_nl($5); # restore newlines
+ local($codethings_defd) = $6;
+ local($aliases) = $7;
+ local($codethings_used) = $8;
+ local($restofline) = $9; # restore newlines
+ # restofline has srcfile on the front...
+ local($srcfilename,$srcfilelineno);
+ $restofline =~ /^(.*)#%%#(.+)#%%#(.*)/;
+ $srcfilename = $1; $srcfilelineno = $2;
+ $restofline = &deatified2verb_nl($3);
+
+ $S++; # new "section"
+
+ $Sec_depth[$S] = $sec_depth;
+ if ($sec_depth == 0) { # this is a magical depth
+ $Sec_abs_depth[$S] = 0;
+ } else {
+ $Sec_abs_depth[$S] = $Base_sec_depth + $Sec_depth_offset + $sec_depth - 1;
+ }
+ if ($Sec_abs_depth[$S] < 0) {
+ &not_OK('???', '???', "section depth not positive: $_");
+ $Sec_abs_depth[$S] = 1;
+ } elsif ($Sec_abs_depth[$S] > $MAX_SEC_DEPTH) {
+ &not_OK('???', '???', "section depth more than $MAX_SEC_DEPTH: $_");
+ $Sec_abs_depth[$S] = $MAX_SEC_DEPTH;
+ }
+ &incr_Sec_vec($Sec_abs_depth[$S]);
+ $Sec_numstr[$S] = join('.',@Sec_vec);
+ $Sec_numstr_exists{$Sec_numstr[$S]} = $S;
+ $Sec_nodename[$S] = $nodename;
+ $Nodename_sec{$nodename} = $S;
+ $Sec_aliases[$S] = $aliases;
+ local($a);
+ foreach $a (split(/,/,$aliases)) { # aliases too
+ $Nodename_sec{$a} = $S if $a;
+ }
+ $Sec_nodespec[$S] = $nodespec;
+ $Sec_title[$S] = $restofline; # this will only be right for lit2texi
+#out $Sec_title[$S] =~ s/\001starred\003//; # will pick up on 2nd pass
+ # maybe should leave it in so \tableofcontents works as expected...
+ $Sec_owner[$S] = $owner;
+ $Sec_extra_menu_entries[$S] = $xtra_menu;
+ $Sec_codethings_used[$S] = $codethings_used;
+ $Sec_codethings_defd[$S] = $codethings_defd;
+ local($d);
+ foreach $d (split(/\001/,$codethings_defd)) {
+ $Codething_defd_sec{$d} = $S if $d;
+ }
+ $Sec_first_blk[$S] = 0; $Sec_last_blk[$S] = -1; # dummies
+ }
+ }
+ &do_std_closes();
+}
+
+sub second_link_pass {
+ $S = -1; # section counter; should be bumped before use!!!
+
+ $Table_of_contents_please = 0;
+
+ # may be only grabbing (-g <node>) a subtree of nodes rooted at
+ # node; so first figure out what sections these are.
+ # NB: the first (pre-amble) and last (\end{document}) sections are
+ # ALWAYS printed.
+ ($First_sec_to_grab, $Last_sec_to_grab) = &calc_grab_range();
+ print STDERR "grab range: $First_sec_to_grab--$Last_sec_to_grab\n" if $Debugging;
+
+ $pipe_string = "$Lit_inputter $Verbose 1 $Litinputs $Input_file";
+ print STDERR "link(2):in=$pipe_string\n" if $Verbose;
+ print STDERR " out=$Link_outfile\n" if $Verbose;
+ &do_std_opens($pipe_string,$Link_outfile);
+
+ &print_setfilename() if $Lit2texi;
+
+ while (<INPIPE>) {
+ if (/^srcfile!_!.*!_!\d+!_!$/) {
+ next; # junk from lit-inputter
+
+ } elsif (/^\001(down|up)section\003$/) {
+ next;
+
+ } elsif (/\001rootsectiontype\003(\d+)\002/) {
+ next;
+
+ } elsif (/\001beginrawlatex\003/) {
+ $_ = <INPIPE>;
+ while ($_ ne '' && ! /\001endrawlatex\003/) {
+ print $_;
+ $_ = <INPIPE>;
+ }
+ next;
+
+ } elsif (/^\001section\003(.+)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)\002(.*)/) {
+ local($sec_depth) = $1;
+ local($nodename) = $2;
+ local($nodespec) = $3;
+ local($owner) = $4;
+ local($xtra_menu) = &deatified2verb_nl($5); # restore newlines
+ local($codethings_defd) = $6;
+ local($aliases) = $7;
+ local($codethings_used) = $8;
+ local($restofline) = $9; # restore newlines
+ # restofline has srcfile on the front...
+ local($srcfilename,$srcfilelineno);
+ $restofline =~ /^(.*)#%%#(.+)#%%#(.*)/;
+ $srcfilename = $1; $srcfilelineno = $2;
+ $restofline = &deatified2verb_nl($3);
+
+ $S++; # new "section"
+
+ # we take sections in the grab range, plus any at
+ # the magic absolute-depth 0 (pre-amble and \end{document},
+ # presumably)
+ #
+ # first an unfortunate hack so that grabbed things start
+ # out on a page of their own
+ print "\\pagebreak\n" if $S == 1 && $Grab_node ne 'Top';
+
+ next if ! ($Sec_abs_depth[$S] == 0
+ || ($S >= $First_sec_to_grab && $S <= $Last_sec_to_grab));
+
+ if ($Lit2texi) {
+ &end_of_section_stuff($S-1) if $S > 0; # end previous section
+
+ print &mk_line_directive($srcfilename,($srcfilelineno - 3))
+ if $srcfilename && $srcfilelineno >= 4;
+ # guessed how much extra junk got put in...
+
+ &print_node_header($S) if $Sec_nodespec[$S];
+
+ if ($Sec_abs_depth[$S] > 0 && $restofline !~ /\001starred\003/) {
+ print "\@",$SECDEPTH_TCMD[$Sec_abs_depth[$S]]," ";
+ print $Sec_title[$S],"\n";
+ print "\n[The `owner' of this section is $owner.]\n\n" if $owner;
+ } elsif ($Sec_abs_depth[$S] > 0) {
+ local($temp_title) = $Sec_title[$S];
+ $temp_title =~ s/\001starred\003//;
+ print "\n$temp_title\n\n";
+ }
+ } elsif ($Lit2latex) {
+ print &mk_line_directive($srcfilename,$srcfilelineno)
+ if $srcfilename && $srcfilelineno >= 1;
+
+ if ($Sec_abs_depth[$S] > 0) {
+ print "\\",$SECDEPTH_LCMD[$Sec_abs_depth[$S]];
+ print "\*" if $restofline =~ /\001starred\003/;
+ local($temp_title) = $Sec_title[$S];
+ $temp_title =~ s/\001starred\003//;
+ print "$temp_title\n";
+ print "\n[The `owner' of this section is $owner.]\n\n" if $owner;
+ }
+ }
+
+ } else {
+ next if ! ($Sec_abs_depth[$S] == 0
+ || ($S >= $First_sec_to_grab && $S <= $Last_sec_to_grab));
+
+ if (/^\001index_uses\003(.*)/ && $Lang_xref !~ /noindex/) {
+ &print_index_entries_for_uses($1);
+
+ } elsif (/^\001xref_uses\003(.*)/) {
+ &print_xrefs_for_uses($1);
+
+ } elsif (/\\[Ss]ectiontype/ || ($Lit2texi && /\@[Ss]ectiontype/)) {
+ s/\@([Ss])ectiontype/\\\1ectiontype/g; # sigh
+ print &subst_sectiontypes('???','???',$_);
+
+ } elsif ($Lit2texi && /\@tableofcontents/) {
+ $Table_of_contents_please = 1;
+
+ } else {
+ if ($Lit2texi) {
+ # some of our xrefs may be to aliases (labels), not to nodenames proper.
+ # sigh
+ while (/\@xref\{([^\}]+)\}/) {
+ local($label) = $1; # assume the guts are clean
+
+ if ( ! defined($Nodename_sec{$label})) {
+ &not_OK('???','???',"I can't dig the \\ref to: $label (no such node?)\n");
+ } else { # canonicalize to real node name
+ $label = $Sec_nodename[$Nodename_sec{$label}];
+ }
+ s/\@xref\{([^\}]+)\}/\@xref!_\{$label\}/; #temp
+ }
+ s/\@xref!_\{/\@xref\{/g; # fix temps
+ }
+ print $_;
+ }
+ }
+ }
+ &do_std_closes();
+}
+
+sub print_setfilename { # make up @setfilename command for Texinfo
+ if ($Infofilename) {
+ print "\@setfilename $Infofilename\n";
+
+ } elsif ($Inputfile_root && $Inputfile_root ne '???') { # it's something reasonable
+ $Infofilename = "$Inputfile_root\.info";
+ print "\@setfilename $Infofilename\n";
+
+ } else {
+ &not_OK("","","can't generate Info file name from inputfile root:$Inputfile_root\n");
+ }
+}
+
+sub print_node_header {
+ local($s) = @_;
+
+ local($this, $next, $prev, $up) = split(/,/, $Sec_nodespec[$s]);
+ local($depth) = $Sec_abs_depth[$s];
+ local($numstr_this) = $Sec_numstr[$s];
+ local(@numstr_this) = split(/\./, $numstr_this);
+
+# print STDERR "this:\t",join('.',@numstr_this),"\n" if $Debugging;
+
+ if ($next eq '?') {
+ # default 'next' node is NEXT one at same depth (-L: or plain NEXT) or NONE
+ local(@numstr_next) = @numstr_this;
+ $numstr_next[$depth] = $numstr_this[$depth] + 1;
+# print STDERR "next:\t",join('.',@numstr_next),"\n" if $Debugging;
+
+ $next = $Sec_numstr_exists{join('.',@numstr_next)};
+ if (defined($next)) {
+ $next = $Sec_nodename[$next];
+ } elsif ($Opt_node_links && defined($Sec_nodename[$s + 1])) {
+ $next = $Sec_nodename[$s + 1];
+ } else {
+ $next = ' ';
+ }
+ }
+
+ if ($prev eq '?') {
+ # default 'prev' node is PREVIOUS one at same depth (-L: or plain PREVIOUS) or NONE
+ # prev will be same as up-node if first section at a level
+ local(@numstr_prev) = @numstr_this;
+ $numstr_prev[$depth] = $numstr_this[$depth] - 1;
+# print STDERR "prev:\t",join('.',@numstr_prev),"\n" if $Debugging;
+
+ $prev = $Sec_numstr_exists{join('.',@numstr_prev)};
+ if (defined($prev)) {
+ $prev = $Sec_nodename[$prev];
+ } elsif ($Opt_node_links && defined($Sec_nodename[$s - 1])) {
+ $prev = $Sec_nodename[$s - 1];
+ } else {
+ $prev = ' ';
+ }
+ }
+
+ if ($up eq '?') {
+ # default 'up' node is same numstr w/ this depth zeroed out
+ # it should always exist, because of default node `Top'
+ local(@numstr_up) = @numstr_this;
+ $numstr_up[$depth] = 0;
+# print STDERR "up:\t",join('.',@numstr_up),"\n" if $Debugging;
+
+ $up = $Sec_numstr_exists{join('.',@numstr_up)};
+ if (! defined($up)) {
+ &not_OK('???','???',
+ "couldn't make up-node from numstr:".join('.',@numstr_up)."\n");
+ $up = 'Top';
+ } else {
+ $up = $Sec_nodename[$up];
+ }
+ }
+
+ print "\n\@node $this, $next, $prev, $up\n";
+ print "\@comment node, next, previous, up\n";
+}
+
+sub calc_grab_range {
+ if ($Grab_node eq 'Top') {
+ return (0, $#Sec_depth); # that is, all sections
+
+ } elsif (! defined($Nodename_sec{$Grab_node})) { # a little error-checking...
+ &not_OK('???','???',"No such node to grab: $Grab_node\n");
+ if ($#Files_to_tidy >= 0) {
+ print STDERR "rm -f @Files_to_tidy\n" if $Verbose;
+ unlink ( @Files_to_tidy );
+ }
+ exit $Status;
+
+ } else {
+ local($first_sec) = $Nodename_sec{$Grab_node}; # that's easy
+ # we now look for the next sec at the same depth;
+ # the sec preceding it will be the last one
+ local($depth) = $Sec_abs_depth[$first_sec];
+ local($first_sec_numstr) = $Sec_numstr[$first_sec];
+ local(@first_sec_numstr) = split(/\./, $first_sec_numstr);
+ local(@next_sec_numstr) = @first_sec_numstr;
+ $next_sec_numstr[$depth] = $first_sec_numstr[$depth] + 1;
+
+ while ($depth >= 1) {
+# print STDERR "next guess=@next_sec_numstr\n";
+
+ if (defined($Sec_numstr_exists{join('.',@next_sec_numstr)})) {
+ return($first_sec,
+ $Sec_numstr_exists{join('.',@next_sec_numstr)} - 1);
+
+ } else { # try next higher level
+ $next_sec_numstr[$depth] = 0;
+ $depth--;
+ $next_sec_numstr[$depth] = $first_sec_numstr[$depth] + 1;
+ }
+ }
+ return ($first_sec, $#Sec_depth);
+ }
+}
+
+sub subst_sectiontypes {
+ local($srcfilename, $srclineno, $_) = @_;
+ local($type);
+
+ while (/\\([Ss])ectiontype\{([^\}]+)\}/) {
+ local($capped) = $1;
+ local($nodename) = $2;
+ if (! defined($Nodename_sec{$nodename})) {
+ &not_OK($srcfilename,$srclineno,"\\sectiontype/ref of unknown node: $nodename (very approx line no)\n");
+ $type = '???failed sectiontype???';
+ } else {
+ local($depth) = $Sec_abs_depth[$Nodename_sec{$nodename}];
+ if (! defined($Sec_abs_depth[$Nodename_sec{$nodename}])) {
+ &not_OK($srcfilename,$srclineno,"failed to do \\sectiontype/ref\n");
+ $type = '???failed sectiontype???';
+ } elsif ($depth >= 3) {
+ $type = 'section';
+ } else {
+ # we use the LaTeX table here ...
+ $type = $SECDEPTH_LCMD[$depth];
+ }
+ if ($capped eq 'S') {
+ local($first) = $type;
+ $first =~ s/^(.).*/\1/;
+ $first =~ y/a-z/A-Z/;
+ local($rest) = $type;
+ $rest =~ s/^.(.*)/\1/;
+ $type = $first . $rest;
+ }
+ }
+ s/\\[Ss]ectiontype\{([^\}]+)\}/$type/g;
+ }
+ $_;
+}
+
+sub end_of_section_stuff { # lit2texi only
+ local($s) = @_;
+
+ @Menu_lines = ();
+ &gen_endofsection_menu_lines($s);
+#print STDERR "1::",@Menu_lines;
+ if ($Sec_extra_menu_entries[$s]) {
+ push(@Menu_lines, "\n");
+ push(@Menu_lines, split(/\n/, $Sec_extra_menu_entries[$s]));
+ }
+#print STDERR "2::",@Menu_lines;
+ push(@Menu_lines, "\n");
+ &gen_codething_menu_lines($s);
+#print STDERR "3::",@Menu_lines;
+ if ($s == 0 && $Table_of_contents_please == 1) {
+ &gen_texinfo_table_of_contents_lines();
+ }
+#print STDERR "4::",@Menu_lines;
+
+ if ( $#Menu_lines >= 1 ) { # more than just what I put there
+ if ($Menu_lines[0] eq "\n") { # nuke a leading blank line
+ shift(@Menu_lines);
+ }
+ print "\n\@menu\n";
+ &format_and_print_menu_lines();
+ print "\@end menu\n";
+ }
+}
+
+sub format_and_print_menu_lines {
+ # just to be beautiful, let's find the longest menu item
+ # (for printing purposes)
+ local($longest_item) = 0;
+ local($ml);
+
+ foreach $ml (@Menu_lines) {
+ if ( $ml =~ /^\*(\s+[^:\n]+):/ ) {
+ local($mi_length) = length( $1 );
+ if ( $mi_length > $longest_item) {
+ $longest_item = $mi_length;
+ }
+ }
+ }
+ # add two to "longest_item" for "::"
+ $longest_item += 2;
+
+ $* = 1;
+ foreach $ml (@Menu_lines) {
+ if ( $ml =~ /^\*(\s+[^:\n]+)(:+)\s*(.*)/ ) {
+ local($m_item) = $1;
+ local($m_sep) = $2;
+ local($m_descr)= $3;
+
+ printf "*%-${longest_item}s %s\n", $m_item.$m_sep, $m_descr;
+ } else {
+ print $ml;
+ }
+ }
+ $* = 0;
+}
+
+sub gen_endofsection_menu_lines {
+ local($s) = @_;
+
+ local($depth) = -1;
+ if ($Sec_abs_depth[$s] > 0) {
+ $depth = $Sec_abs_depth[$s] + 1;
+ } elsif ($Sec_abs_depth[$s] == 0) {
+ $depth = $Sec_depth_offset; # where rootsectiontype takes us
+ }
+ die "got depth $depth when doing print_endofsection_menu\n" if $depth < 0;
+
+ local(@numstr_subsec) = split(/\./, $Sec_numstr[$s]);
+ $numstr_subsec[$depth] = 1; # 1st subsection, if it exists
+
+ $n = $Sec_numstr_exists{join('.',@numstr_subsec)};
+
+ while (defined($n) && $n > 0) {
+
+ local($temp_title) = $Sec_title[$n];
+ $temp_title =~ s/\001starred\003//;
+
+ push(@Menu_lines, "* $Sec_nodename[$n]:: $temp_title.\n");
+
+ $numstr_subsec[$depth] = $numstr_subsec[$depth] + 1;
+ $n = $Sec_numstr_exists{join('.',@numstr_subsec)};
+ }
+}
+
+sub gen_codething_menu_lines {
+ local($s) = @_;
+ # generate menu entries for (defined) codethings that have been used
+ # in this section. (don't print if definition is merely elsewhere in
+ # this section).
+
+ local($u);
+ foreach $u (split(/\001/, $Sec_codethings_used[$s])) {
+ if (defined($Codething_defd_sec{$u})) {
+ local($item_name) = $u;
+ $item_name =~ s/\@/\@\@/g;
+ local($sec_defd_in) = $Codething_defd_sec{$u};
+ local($node_defd_in) = $Sec_nodename[$sec_defd_in];
+ push(@Menu_lines, "\* $item_name: $node_defd_in.\n") if $sec_defd_in != $s;
+ }
+ }
+}
+
+sub print_index_entries_for_uses {
+ local($uses) = @_;
+
+#no # print entries for the used things that HAVE definitions
+ local($u);
+ foreach $u (split(/\001/, $uses)) {
+# if (defined($Codething_defd_sec{$u})) {
+ if ($Lit2texi) {
+ print "\@cindex ".&mk_texi_index_entry($u)."\n";
+ } else {
+ # thinking about a "\|ttize" in there, too
+ print "\\index\{".&mk_latex_index_entry('tt',$u)."\}\%\n";
+ }
+# }
+ }
+}
+
+sub print_xrefs_for_uses { # latex only
+ local($uses) = @_;
+
+ return if ! $Codedef_blurbs; # some people don't want them
+
+ # print entries for the used things that HAVE definitions
+ local(@use) = split(/\001/, $uses);
+ local($u);
+ local($i) = 0;
+ while ( $i <= $#use ) {
+ $u = $use[$i];
+ if (defined($Codething_defd_sec{$u})) {
+ # fiddling must match that in lit-2latex
+ local($fiddled_u);
+ ($fiddled_u = $u) =~ s/\%/<percent>/g; # and other funny chars?
+ $fiddled_u =~ s/\$/<dollar>/g;
+ $fiddled_u =~ s/\\/<slash>/g;
+
+ $use[$i] = &std_mk_code_frag($u) . ": p.~\\pageref\{def::$fiddled_u\}\%\n";
+ # really should use lang-specific "mk_code_frag" but at
+ # link time we don't necessarily know what language is
+ # called for... and it could vary through a big document
+ $i++;
+ } else { # not defined -- remove it
+ splice(@use, $i, 1);
+ }
+ }
+ $u = join('; ',@use); # join up
+ print "\n\n\{\\small \[Definitions: $u\]\}\n\n" if $u;
+}
+
+# a trailing 1 seems to be the habit for inc'd perl files
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-reader.lprl b/web/glasgow/lit2x-0.16/literate/lit-reader.lprl
new file mode 100644
index 0000000000..58d7f179c7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-reader.lprl
@@ -0,0 +1,588 @@
+This code involves looking at the input and stuffing it in the
+right global data structure. You may wish to consult the description
+of said structures (\sectionref{Global_data}).
+
+\begin{code}
+sub read_and_categorize_input {
+
+ local($gobbling) = ''; # more on this below
+
+ $S = $B = 0; # initialise section and block counters
+
+ line: while (<INPIPE>) {
+ $Srcfile_lineno++;
+
+ study; # to speed up regexp matching ???
+
+ # first, deal with magic "srcfile" lines from `lit-inputter'
+ # (lest they be "gobbled")
+ if (/^srcfile!_!(.*)!_!(.*)!_!$/) {
+ $Srcfile_name = $1;
+ $Srcfile_lineno = $2 - 1; # will be incr next time thru
+ #
+ # kick over to a new blk
+ # if not empty, start another block of same type
+ # otherwise, kick curr one again to insert the srcfilename/lineno
+ # (No: this doesn't work -- we can, e.g., get lots of little
+ # "tabular" envs, which is junk.)
+ #
+# &incr_blk_ctr() if ! &empty_blk_p($B);
+# &append_to_curr_blk($Blk_type[$B],'');
+
+ next line;
+ }
+
+ # Next, we worry about the \begin/\end's that serve only to
+ # include/exclude code. These are "onlylatex", "onlyinfo",
+ # "onlypartofdoc", "onlystandalone".
+ #
+ # this is a dull-witted implementation and things can go badly wrong
+ # if the input has errors
+ #
+ if (/^\\(begin|end)\{(onlylatex|onlyinfo|onlypartofdoc|onlystandalone)\}/) {
+ local($begin_or_end) = $1;
+ local($b_or_e_what) = $2;
+
+ $Only_latex = (($begin_or_end eq 'begin') ? 1 : 0) if $b_or_e_what eq 'onlylatex';
+ $Only_info = (($begin_or_end eq 'begin') ? 1 : 0) if $b_or_e_what eq 'onlyinfo';
+ $Only_partofdoc = (($begin_or_end eq 'begin') ? 1 : 0) if $b_or_e_what eq 'onlypartofdoc';
+ $Only_standalone = (($begin_or_end eq 'begin') ? 1 : 0) if $b_or_e_what eq 'onlystandalone';
+
+ next line; # finished with this line
+ }
+ next line if $Only_latex && ! $Lit2latex;
+ next line if $Only_info && ! $Lit2texi;
+ next line if $Only_partofdoc && $Standalone_doc;
+ next line if $Only_standalone && (! $Standalone_doc);
+
+ # Now, we worry about "gobbling": that is, once we've seen a
+ # \begin{somethingInteresting}, we want to gobble everything up to
+ # the \end{somethingInteresting} -- no ifs, ands, buts or nesting!
+ # these are \begin/\end's that suggest _categories_ of stuff
+ # (text, code, etc.)
+
+ # the two arguments to std_gobbling_stuff says how to categorize
+ # an ordinary line and an \end{somethingInteresting} line.
+
+ if ($gobbling) {
+
+ if ($gobbling eq 'change') { # not really implemented
+ $gobbling = &std_gobbling_stuff('TOSS IT','TOSS IT');
+
+ } elsif ($gobbling eq 'test') { # ditto
+ $gobbling = &std_gobbling_stuff('TOSS IT','TOSS IT');
+
+ } elsif ($gobbling eq 'verbatim') {
+ $gobbling = &std_gobbling_stuff('verb','NEW BLK ONLY');
+ } elsif ($gobbling eq 'flushverbatim') {
+ $gobbling = &std_gobbling_stuff('flushverb','NEW BLK ONLY');
+
+ } elsif ($gobbling eq 'display') {
+ $gobbling = &std_gobbling_stuff('txt','txt');
+ } elsif ($gobbling eq 'flushdisplay') {
+ $gobbling = &std_gobbling_stuff('txt','txt');
+
+ } elsif ($gobbling eq 'pseudocode') {
+ $gobbling = &std_gobbling_stuff('pseudocode','NEW BLK ONLY');
+
+ } elsif ($gobbling eq 'tabular') {
+ $gobbling = &std_gobbling_stuff('tabular','NEW BLK ONLY');
+
+ } elsif ($gobbling eq 'menu') {
+ $gobbling = &std_gobbling_stuff(
+ ($Lit2texi) ? 'menu' : 'TOSS IT',
+ ($Lit2texi) ? 'NEW BLK ONLY' : 'TOSS IT');
+
+ } elsif ($gobbling eq 'rawlatex') {
+ $gobbling = &std_gobbling_stuff(
+ ($Lit2latex) ? 'rawlatex' : 'TOSS IT',
+ ($Lit2latex) ? 'NEW BLK ONLY' : 'TOSS IT');
+
+ # rawtexinfo is too hard (and not that useful?)
+
+ } elsif ($gobbling eq 'code') {
+ $gobbling = &std_gobbling_stuff('code','NEW BLK ONLY');
+
+ } elsif ($gobbling eq 'bird-code') { # > Bird-track code lines
+ if (/^>.*/) { # append...
+ s/^>// if $Lang_typeset =~ /nobird/; # coerce to non-Bird
+ &append_to_curr_blk('code', $_);
+ } else { # it's over... (in trouble if this is \begin...)
+ &incr_blk_ctr();
+ &append_to_curr_blk('txt',$_);
+ $gobbling = ''; # finished
+ }
+ }
+ next line; # outta here...
+ }
+
+ # now let's do all the stuff that gets us gobbling
+ #
+
+ # change/test: not implemented
+ if (/^\\begin\{(change|test)\}/) { # not implemented
+ $gobbling = $1;
+ # just a warning
+ print STDERR "$Srcfile_name:$Srcfile_lineno: \\begin/\\end\{$1\} not implemented yet [warning]\n";
+
+ } elsif (/^\\begin\{verbatim\}/) {
+ $gobbling = 'verbatim';
+ &incr_blk_ctr();
+ } elsif (/^\\begin\{flushverbatim\}/) {
+ $gobbling = 'flushverbatim';
+ &incr_blk_ctr();
+
+ # special handling of display so we can put \hfil\break onto each
+ # line (for lit2latex)
+ } elsif (/^\\begin\{display\}/) { # no new block here
+ $gobbling = 'display';
+ &append_to_curr_blk('txt',$_);
+ } elsif (/^\\begin\{flushdisplay\}/) {
+ $gobbling = 'flushdisplay';
+ &append_to_curr_blk('txt',$_);
+
+ } elsif (/^\\begin\{pseudocode\}/) {
+ $gobbling = 'pseudocode';
+ &incr_blk_ctr();
+
+ } elsif (/^\\begin\{tabular\}(.*)/) {
+ $gobbling = 'tabular';
+ &incr_blk_ctr(); # for new tabular blk
+ &set_blk_magic_info($1); # the main thing!
+
+ } elsif (/^\\begin\{menu\}/) {
+ $gobbling = 'menu';
+ &incr_blk_ctr() if $Lit2texi; # for new menu blk
+
+ } elsif (/^\\begin\{rawlatex\}/) {
+ $gobbling = 'rawlatex';
+ &incr_blk_ctr() if $Lit2latex; # for new blk
+
+ } elsif (/^\\begin\{code\}/) {
+ $gobbling = 'code';
+ if (/\\begin\{code\}\[(.+)\]/) { # named ribbons...
+ $ribbon_names = $1;
+ $ribbon_names =~ s/\s*,\s*/,/g; # rm spaces around commas
+ } else { # implicitly more of code ribbon <<main>>
+ $ribbon_names = 'main';
+ }
+ &incr_blk_ctr(); # for new code blk
+ &set_blk_magic_info($ribbon_names); # the main thing!
+
+ # record this block's number in %Ribbon_blks
+ local(@ribbons) = split(/,/,$ribbon_names);
+ local($r);
+ foreach $r (@ribbons) {
+ if ($Ribbon_blks{$r}) {
+ $Ribbon_blks{$r} .= ",$B";
+ } else { # first block
+ $Ribbon_blks{$r} = $B;
+ }
+ }
+
+ } elsif (/^>.*/) {
+ $gobbling = 'bird-code';
+ &incr_blk_ctr(); # for new code blk
+
+ s/^>// if $Lang_typeset =~ /nobird/; # coerce to non-Bird
+ &append_to_curr_blk('code', $_);
+
+ # incr srclineno, because it may later be fiddled downwards
+ $Blk_srcfile_lineno[$B]++ if ! $Lit2pgm;
+ &set_blk_magic_info('main');
+
+ if ($Ribbon_blks{'main'}) {
+ $Ribbon_blks{'main'} .= ",$B";
+ } else { # first block
+ $Ribbon_blks{'main'} = $B;
+ }
+ }
+
+ next line if $gobbling; # now set...
+
+ # in alphabetical order, magical things to look for while categorizing
+
+ if (/\\author\{(.+)\}/) {
+ if ($Lit2texi) {
+ $Doc_author = &deatified2verb($1);
+ $Doc_author =~ s/\\\\/\n\\center /g;
+ } else {
+ &append_to_curr_blk('txt',$_);
+ }
+ next line; # to help perl
+
+ } elsif ($Lit2texi && /^\\appendix/) {
+ # tossed
+ next line; # to help perl
+
+ } elsif ($Lit2texi && /^\\caption\{(.*)\}/) {
+ &append_to_curr_blk('txt',"CAPTION: $1\n");
+ next line; # to help perl
+
+ } elsif (/\\date\{(.+)\}/) {
+ if ($Lit2texi) {
+ $Doc_date = &deatified2verb($1);
+ $Doc_date =~ s/\\\\/\n\\center /g;
+ } else {
+ &append_to_curr_blk('txt',$_);
+ }
+ next line; # to help perl
+
+ } elsif (/^\\define\{\\(.*)\}\s*\{(.*)\}/) {
+ $Define{$1} = $2;
+ # text not saved
+ next line; # to help perl
+
+ } elsif (/^\\end\{document\}/) { # a magic section all its own!
+ &start_new_section();
+ &incr_Sec_vec(0); # magical depth
+ $Sec_numstr[$S] = join('.',@Sec_vec);
+
+ $Sec_depth[$S] = 0; # magic value for \begin/\end{document}
+ $Sec_nodename[$S]=''; # so a \001section\003 line will not be dumped for it
+
+ $Sec_nodename[$S] = 'Bottom';
+ # $Nodename_sec{'Bottom'} = $S; # no need for this
+
+ &append_to_curr_blk('txt',$_) if $Lit2latex;
+ &append_to_curr_blk('txt','') if ! $Lit2latex; # need something there
+ next line; # to help perl
+
+ } elsif (/^\\documentstyle(.*)\{(\w+)\}$/) { # says what top-level section should be
+ local($style_options) = $1;
+ local($document_type) = $2;
+
+ $Standalone_doc = 1;
+
+ $Sec_depth[0] = 0;
+ # makes node 'Top' start to exist (?)
+ &incr_Sec_vec(0); # magical depth
+ $Sec_numstr[0] = join('.',@Sec_vec);
+
+ $Sec_nodename[0] = 'Top';
+ $Nodename_sec{'Top'} = 0;
+ $Sec_nodespec[0] = 'Top,,,(dir)';
+
+ # depths are set so that top-level menu of sections can be constructed
+ if ($document_type eq 'report' || $document_type eq 'book') {
+ # \section1 is a "chapter"
+ # save info in weird form
+ &append_to_curr_blk('txt',"\001rootsectiontype\0032\002\n");
+ } elsif ($document_type eq 'article') {
+ # \section1 is a "section"
+ &append_to_curr_blk('txt',"\001rootsectiontype\0033\002\n");
+ } else {
+ &not_OK($Srcfile_name, $Srcfile_lineno,
+ "don't recognise document type: $document_type\n");
+ }
+
+ # strip the literate style option and put in an explicit \input
+ # this ensures we get the version we want
+ $style_options =~ s/\bliterate\b//;
+ $style_options =~ s/,,/,/; # tidy any mess
+ $style_options =~ s/^\[,/\[/;
+ $style_options =~ s/,\]$/\]/;
+ $style_options =~ s/^\[\]$//;
+ if ($Lit2latex) {
+ &append_to_curr_blk('txt',"\\documentstyle$style_options\{$document_type\}\n");
+ # \input is split over two lines so lit-inputter won't recognize it but LaTeX will
+ &append_to_curr_blk('txt',"\\input%\n");
+ &append_to_curr_blk('txt',"\{$LIB_DIR/lit-style.tex\}\n");
+ }
+ next line; # to help perl
+
+ }
+ # split here to help perl
+ if (/^\\downsection/) { # save in weird form
+ &append_to_curr_blk('txt',"\001downsection\003\n");
+ next line; # to help perl
+
+ } elsif ($Lit2texi && /^\\(begin|end)\{figure\}/) {
+ #tossed
+ next line; # to help perl
+
+ } elsif (! $Lit2pgm && /^\\input\{(.*)\}/) {
+ local($iname) = $1;
+ local($newsuff) = ($Lit2texi) ? 'itxi' : 'itex';
+
+ # change name to the expected suffix or add it if it doesn't have it
+ # cf setting Inputfile_root, etc. in lit2stuff driver
+ if ($iname =~ /\.lit\.[^\.\/]+$/) { # a .lit.<xx> suffix
+ $iname =~ s/\.lit\.[^\.\/]+$/\.$newsuff/;
+ } elsif ($iname =~ /\.[^\.\/]+$/) {
+ $iname =~ s/[^\.\/]+$/$newsuff/;
+ } else {
+ $iname .= ".$newsuff";
+ }
+ &append_to_curr_blk('txt',"\\input\{$iname\}\n");
+ next line; # to help perl
+
+ } elsif (/^\\clear(doublepage|page)/) {
+ &append_to_curr_blk('txt',$_) if $Lit2latex;
+ next line; # to help perl
+
+ } elsif (/^\\listof(figures|tables)/) {
+ &append_to_curr_blk('txt',$_) if $Lit2latex;
+ next line; # to help perl
+
+ } elsif ($Lit2texi && /^\\infocommand\{\\(.*)\}\s*\{(.*)\}/) {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "\\infocommand is obsolete; pls use \\define\n");
+ # text not saved
+ next line; # to help perl
+
+ # \label's require a bit of extra stuff; see below
+
+ } elsif (/^\\makeindex/) {
+#ignored &append_to_curr_blk('txt',$_) if $Lit2latex;
+ next line; # to help perl
+
+ } elsif (/\\menuentry\{(.+)\}\{(.+)\}/) {
+ if ($Lit2texi) {
+ local($tag) = $1;
+ local($descr) = $2;
+ $Sec_extra_menu_entries[$S] .= "\* $tag::\t$descr\n";
+ }
+ next line; # to help perl
+
+ } elsif (! $Lit2texi && /\\node\{.*\}/) {
+ # toss it
+ next line; # to help perl
+
+ } elsif (/\\owner\{([^\}]+)\}/) {
+ local($owner_name) = &deatified2verb($1);
+
+ $Sec_owner[$S] = $owner_name;
+ next line; # to help perl
+ }
+
+ # split here to help perl
+ if (/^\\printindex/) { # sectioning-like things need doing for Texinfo
+
+ if ($Lit2latex) { # hmm... means index might get tacked on when -g used
+# &append_to_curr_blk('txt',$_);
+
+ # manufacture a top-level section [very carefully]
+ # otherwise you can get index entries pinned on after the
+ # \printindex
+ &start_new_section();
+ $Sec_depth[$S] = 1 ;
+ $Sec_title[$S] = ''; # no title
+ &incr_Sec_vec( 1 );
+ $Sec_numstr[$S] = join('.',@Sec_vec);
+ $Sec_numstr_exists{$Sec_numstr[$S]} = $S;
+ $Sec_nodename[$S] = ''; # no nodename
+ $Nodename_sec{'Index'} = $S;
+ $Sec_nodespec[$S] = '';
+
+ &append_to_curr_blk('txt',$_);
+
+ } elsif ($Lit2texi) {
+ # manufacture a top-level section
+ # (gaze in handle_sectioning_line, for enlightenment...)
+ &start_new_section();
+ $Sec_depth[$S] = 1 ;
+ $Sec_title[$S] = 'Index';
+ &incr_Sec_vec( 1 );
+ $Sec_numstr[$S] = join('.',@Sec_vec);
+ $Sec_numstr_exists{$Sec_numstr[$S]} = $S;
+ $Sec_nodename[$S] = 'Index';
+ $Nodename_sec{'Index'} = $S;
+ $Sec_nodespec[$S] = 'Index,?,?,?';
+
+ &append_to_curr_blk('txt',"\\printindex cp\n");
+ }
+ next line; # to help perl
+ } elsif (/^\\rootsectiontype\{\\(\w+)\}/ || /^\\rootsectiontype\{(\w+)\}/) {
+ if ( ! defined($SECCMD_DEPTH{$1})) {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "bogus \\rootsectiontype: $1\n");
+ }
+ # saved in weird form
+ &append_to_curr_blk('txt',"\001rootsectiontype\003$SECCMD_DEPTH{$1}\002\n");
+ next line; # to help perl
+
+ } elsif ( ! /^\\section(type|ref)/
+ && (/^\\section[^A-Za-z]/ || /^\\(sub){1,3}section/)) {
+ # quick, zap the synonyms...
+ s/^\\section([^\d])/\\section1\1/;
+ s/^\\subsubsubsection/\\section4/;
+ s/^\\subsubsection/\\section3/;
+ s/^\\subsection/\\section2/;
+
+ # now the real work
+ &start_new_section();
+ &handle_sectioning_line();
+ next line; # to help perl
+
+ } elsif (/(.*)\\standaloneornot\{(.*)\}\{(.*)\}(.*\n)/) {
+ local($before) = $1;
+ local($ifso_text) = &deatified2verb_nl($2);
+ local($ifnot_text) = &deatified2verb_nl($3);
+ local($after) = $4;
+
+ &append_to_curr_blk('txt',"$before$ifso_text$after") if $Standalone_doc;
+ &append_to_curr_blk('txt',"$before$ifnot_text$after") if ! $Standalone_doc;
+ next line; # to help perl
+
+ } elsif (/^\\suppresscomments/) {
+ &append_to_curr_blk('txt',$_) if $Lit2latex;
+ &not_OK($Srcfile_name,$Srcfile_lineno,"can't \\suppresscomments in Info files (warning)\n") if $Lit2texi;
+ next line; # to help perl
+
+ } elsif (/^\\suppressmenu/) {
+ &not_OK($Srcfile_name,$Srcfile_lineno,"\\suppressmenu not implemented\n");
+ next line; # to help perl
+
+ } elsif ($Lit2texi && /^\\(begin|end)\{table\}/) {
+ # tossed
+ next line; # to help perl
+
+ } elsif (/^\\tableofcontents/) {
+ &append_to_curr_blk('txt',$_);
+ next line; # to help perl
+
+ } elsif (/\\title\{(.+)\}/) {
+ if ($Lit2texi) {
+ $Doc_title = &deatified2verb($1);
+ $Doc_title =~ s/\\\\/\n\\center /g;
+ } else {
+ &append_to_curr_blk('txt',$_);
+ }
+ next line; # to help perl
+
+ } elsif (/^\\upsection/) { # save in weird form
+ &append_to_curr_blk('txt',"\001upsection\003\n");
+ next line; # to help perl
+
+ } else { # just some random line of text
+
+ # go after \label's
+ while ( ! $Lit2pgm && /\\label\{([^\}]+)\}/) {
+ local($label_name) = &deatified2verb($1);
+
+ if (defined($Nodename_sec{$label_name})) {
+ &not_OK($Srcfile_name,$Srcfile_lineno,"$label_name already used as a label or nodename\n");
+ } else {
+ $Nodename_sec{$label_name} = $S; # new alias for this section
+ $Sec_aliases[$S] .= "$label_name,";
+ }
+ s/\\label\{([^\}]+)\}// if $Lit2texi;
+ s/\\label\{/\\label!_\{/ if $Lit2latex; # temp
+ }
+ s/\\label!_\{/\\label\{/g if $Lit2latex; # untemp
+
+ &append_to_curr_blk('txt',$_);
+ }
+ }
+ # wind up last section
+ $Sec_last_blk[$S] = $B;
+}
+
+sub std_gobbling_stuff { # looks at $_
+ # args say what to do with ordinary line ($curr_type)
+ # and what to do if \end{$gobbling} seen
+ local($curr_type, $end_type) = @_;
+
+ if (/^\\end\{$gobbling\}/) { # it's over...
+
+ if ($end_type eq 'NEW BLK ONLY') {
+ &incr_blk_ctr();
+
+ } elsif ($end_type ne 'TOSS IT') {
+ &incr_blk_ctr();
+ &append_to_curr_blk($end_type, $_);
+ }
+
+ $gobbling = ''; # finished
+
+ } elsif ($curr_type ne 'TOSS IT') { # just append...
+
+ # magic stuff for code and (flush)display
+ $_ = '>'.$_ if $gobbling eq 'code' && $Lang_typeset =~ /\bbird/;
+ s/\n$/\\hfil\\break\n/ if $Lit2latex && $gobbling =~ /display$/;
+
+ &append_to_curr_blk($curr_type, $_);
+ }
+ # new $gobbling value returned
+ $gobbling;
+}
+
+sub handle_sectioning_line { # part of categorizing input
+ local($sec_depth,$title,$node_spec) = ('', '', '');
+
+ if (/^\\section(\d+)\*\[([^\]]+)\]\{(.*)\}\s*\n/) { # given title, node-spec (STARRED)
+ $sec_depth = $1; $node_spec = $2; $title = "\001starred\003$3";
+ $node_spec .= ',?,?,?' unless $node_spec =~ /,/;
+
+ } elsif (/^\\section(\d+)\[([^\]]+)\]\{(.*)\}\s*\n/) { # given title, node-spec
+ $sec_depth = $1; $node_spec = $2; $title = $3;
+ $node_spec .= ',?,?,?' unless $node_spec =~ /,/;
+
+ } elsif (/^\\section(\d+)\*\{(.*)\}\s*\n/) { # given title, default node-spec (STARRED)
+ $sec_depth = $1; $node_spec = '?,?,?,?'; $title = "\001starred\003$2";
+
+ } elsif (/^\\section(\d+)\{(.*)\}\s*\n/) { # given title, default node-spec
+ $sec_depth = $1; $title = $2; $node_spec = '?,?,?,?';
+
+ } else {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "hey, sectioning command has me confused: $_");
+ }
+ if ($sec_depth <= 0) {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "section depth not positive: $_");
+ $sec_depth = 1;
+ } elsif ($sec_depth > $MAX_SEC_DEPTH) {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "section depth more than $MAX_SEC_DEPTH: $_");
+ $sec_depth = $MAX_SEC_DEPTH;
+ }
+
+ $Sec_title[$S] = $title; # stored as deatified ...
+ $Sec_title[$S] =~ s/\001newline\003/ /g; # but the newlines go
+ $Sec_depth[$S] = $sec_depth;
+ &incr_Sec_vec($Sec_depth[$S]);
+
+ $Sec_numstr[$S] = join('.',@Sec_vec);
+ $Sec_numstr_exists{$Sec_numstr[$S]} = $S;
+
+ $node_spec =~ s/^\s+//; # tidy up
+ $node_spec =~ s/\s+$//; # no leading/trailing spaces
+ $node_spec =~ s/\s*,\s*/,/g; # no spaces around commas
+
+ if ($node_spec =~ /^\?(,.*)/) {
+ local($rest_of_nodespec) = $1;
+ # default node name is root of input filename + section number
+ $Sec_nodename[$S] = $Inputfile_root
+ . '_' . &tidy_numstr($Sec_numstr[$S])
+ . $Nodename_suffix;
+ $Sec_nodespec[$S] = $Sec_nodename[$S] . $rest_of_nodespec;
+ } elsif ($node_spec =~ /^([^,\?]+)(,.*)/) {
+ $Sec_nodename[$S] = $1 . $Nodename_suffix;
+ local($rest_of_nodespec) = $2;
+ $Sec_nodespec[$S] = $Sec_nodename[$S] . $rest_of_nodespec;
+ } else {
+ &not_OK($Srcfile_name, $Srcfile_lineno, "node_spec has me confused: $node_spec\n");
+ }
+ $Nodename_sec{$Sec_nodename[$S]} = $S;
+}
+
+sub fiddle_line_numbers {
+ # there are some off-by-one errors in line numbers, because of the
+ # way things are recorded in read_and_categorize_input. try to fix.
+ local($S, $B);
+
+ foreach ($S = 0; $S <= $#Sec_depth; $S++) {
+ foreach ($B = $Sec_first_blk[$S]; $B <= $Sec_last_blk[$S]; $B++) {
+
+ # all the things where the \begin{something}/\end{something}
+ # isn't kept
+
+ $Blk_srcfile_lineno[$B]--
+ if ($Blk_type[$B] =~ /^(code|pseudocode)$/)
+ || ($Blk_type[$B] eq 'menu')
+ || ($Blk_type[$B] eq 'tabular')
+ || ($Blk_type[$B] =~ /verb$/);
+ }
+ }
+}
+
+# keeps the including 'do' happy
+1;
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/literate/lit-style.tex b/web/glasgow/lit2x-0.16/literate/lit-style.tex
new file mode 100644
index 0000000000..7ffd7603a0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit-style.tex
@@ -0,0 +1,1152 @@
+% THIS FILE IS AUTOMATICALLY INPUT INTO GLASGOW LITERATE DOCUMENTS
+%
+% support for "literate programming" with Haskell (and other things)
+% contact: Will Partain (partain@dcs.glasgow.ac.uk)
+%
+% most of it is copies of semi-std .sty files;
+% done this way so we don't have to rely on others having them
+
+\newcommand{\ToDo}[1]{$\spadesuit$~{\bf ToDo:} {\em #1} $\spadesuit$}
+\newcommand{\srcloc}[1]{\marginpar{\footnotesize\tt #1}}
+\newcommand{\smiley}{%
+\hbox{$\bigcirc\mskip-13.3mu{}^{..}
+\mskip-11mu\scriptscriptstyle\smile\ $}}
+
+\makeatletter
+
+%% basic format, for better or worse, is "Simon's format"
+%% intended for 11pt work
+%%
+%===================================================================
+%\input{a4wide.sty}
+%NAME: a4wide.sty
+% "moretext" document style option.
+% Jean-Francois Lamy, July 86
+%
+% Redefines the margins so that they are more in line with
+% what we are used to see.
+%
+
+%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%\input a4.sty
+%%
+%% This file was generated with `docstrip.tex' version v1.0b <89/11/05>
+%%
+%% The original source file was `a4.doc'.
+%%
+%% IMPORTANT NOTICE:
+%% You are not allowed to distribute this file.
+%% For distribution of the original source see
+%% the copyright notice in the file `a4.doc'.
+%%
+\def\fileversion{1.2}
+\def\filedate{26 Feb 90}
+\def\docdate {26 Feb 90}
+%% \CheckSum{134}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+%%\typeout{Style option `A4' \fileversion\space<\filedate> (NP and JLB)}
+%%\typeout{English documentation\space\space\space<\docdate> (JLB)}
+\topmargin 0pt
+\ifcase \@ptsize
+ \textheight 53\baselineskip
+\or
+ \textheight 46\baselineskip
+\or
+ \textheight 42\baselineskip
+\fi
+\advance\textheight by \topskip
+\ifcase \@ptsize
+ \textwidth 5.00in
+ \marginparwidth 1.00in
+ \if@twoside
+ \oddsidemargin 0.55in
+ \evensidemargin 0.75in
+ \else
+ \oddsidemargin 0.55in
+ \evensidemargin 0.55in
+ \fi
+\or
+ \textwidth 5.20in
+ \marginparwidth 1.00in
+ \if@twoside
+ \oddsidemargin 0.45in
+ \evensidemargin 0.65in
+ \else
+ \oddsidemargin 0.45in
+ \evensidemargin 0.45in
+ \fi
+\or
+ \textwidth 5.70in
+ \marginparwidth 0.80in
+ \if@twoside
+ \oddsidemargin 0.20in
+ \evensidemargin 0.40in
+ \else
+ \oddsidemargin 0.20in
+ \evensidemargin 0.20in
+ \fi
+\fi
+\def\WideMargins{%
+ \newdimen\ExtraWidth
+ \ifcase \@ptsize
+ \ExtraWidth = 0.5in
+ \@widemargins
+ \or
+ \ExtraWidth = 0.5in
+ \@widemargins
+ \or
+ \ExtraWidth = 0.7in
+ \@widemargins
+ \fi\let\WideMargins\relax\let\@widemargins\relax}
+{\def\do{\noexpand\do\noexpand}
+ \xdef\@preamblecmds{\@preamblecmds \do\WideMargins}
+}
+\def\@widemargins{%
+ \global\advance\textwidth by -\ExtraWidth
+ \global\advance\marginparwidth by \ExtraWidth
+ \if@twoside
+ \tw@sidedwidemargins
+ \else
+ \@nesidedwidemargins
+ \fi}
+\def\tw@sidedwidemargins{%
+ \if@reversemargin
+ \@tempdima=\evensidemargin
+ \advance\@tempdima by -\oddsidemargin
+ \advance\oddsidemargin by \ExtraWidth
+ \advance\oddsidemargin by \@tempdima
+ \advance\evensidemargin by -\@tempdima
+ \else
+ \advance\evensidemargin by \ExtraWidth
+ \fi}
+\def\@nesidedwidemargins{%
+ \if@reversemargin
+ \advance\oddsidemargin by \ExtraWidth
+ \advance\evensidemargin by \ExtraWidth
+ \fi}
+%\endinput
+% end of a4.sty
+%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\ifcase \@ptsize
+ % mods for 10 pt
+ \oddsidemargin 0.15 in % Left margin on odd-numbered pages.
+ \evensidemargin 0.35 in % Left margin on even-numbered pages.
+ \marginparwidth 1 in % Width of marginal notes.
+ \oddsidemargin 0.25 in % Note that \oddsidemargin = \evensidemargin
+ \evensidemargin 0.25 in
+ \marginparwidth 0.75 in
+ \textwidth 5.875 in % Width of text line.
+\or % mods for 11 pt
+ \oddsidemargin 0.1 in % Left margin on odd-numbered pages.
+ \evensidemargin 0.15 in % Left margin on even-numbered pages.
+ \marginparwidth 1 in % Width of marginal notes.
+ \oddsidemargin 0.125 in % Note that \oddsidemargin = \evensidemargin
+ \evensidemargin 0.125 in
+ \marginparwidth 0.75 in
+ \textwidth 6.125 in % Width of text line.
+\or % mods for 12 pt
+ \oddsidemargin -10 pt % Left margin on odd-numbered pages.
+ \evensidemargin 10 pt % Left margin on even-numbered pages.
+ \marginparwidth 1 in % Width of marginal notes.
+ \oddsidemargin 0 in % Note that \oddsidemargin = \evensidemargin
+ \evensidemargin 0 in
+ \marginparwidth 0.75 in
+ \textwidth 6.375 true in % Width of text line.
+\fi
+% end of a4wide.sty
+%===================================================================
+
+% Block paragraphs
+% NOTE: comment out these four lines if you want more
+% standard LaTeX-looking paragraphs.
+\setlength{\parskip}{0.25cm}
+% partain: save the parindent value, for indenting code
+\newlength{\litcodeindent}
+\setlength{\litcodeindent}{\z@}
+%\setlength{\litcodeindent}{\parindent}
+% comment out this one line if you want std para indentation:
+\setlength{\parindent}{0cm}
+%\renewcommand{\textfraction}{0.2}
+%\renewcommand{\floatpagefraction}{0.7}
+
+% display environment: same as "quotation"
+\def\display{\list{}{\listparindent \z@
+ \itemindent\listparindent
+ \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]}
+\let\enddisplay=\endlist
+
+% flushdisplay environment: same as "display" but without indent
+\def\flushdisplay{\list{}{\listparindent \z@
+ \itemindent\listparindent
+ \leftmargin\z@ \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]}
+\let\endflushdisplay=\endlist
+
+% unflushverbatim environment: "verbatim" is naturally "flush"
+% so this simply arranges "unflushness". It presumes things are written as...
+% \begin{unflushverbatim}
+% \begin{verbatim}
+% <stuff>
+% \end{verbatim}
+% \end{unflushverbatim}
+%
+\def\unflushverbatim{\list{}{\listparindent \z@
+ \itemindent\listparindent
+ \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]}
+\let\endunflushverbatim=\endlist
+
+%\newcommand{\BeginLitCode}{\par\noindent\begin{tabular}{@{\hspace*{1.2em}}l@{}}}
+%\newcommand{\BeginLitCodeNoIndent}{\par\noindent\begin{tabular}{@{}l@{}}}
+%\newcommand{\EndLitCode}{\end{tabular}}
+
+% same, for now
+%\newcommand{\BeginLitVerb}{\par\noindent\begin{tabular}{@{\hspace*{1.2em}}l@{}}}
+%\newcommand{\BeginLitVerbNoIndent}{\par\noindent\begin{tabular}{@{}l@{}}}
+%\newcommand{\EndLitVerb}{\end{tabular}}
+
+% and some internal variants that set the page numbers differently
+\newcommand{\indexttit}[1]{\index{#1@{\tt #1}|itindexpage}}
+\newcommand{\itindexpage}[1]{{\it #1}}
+%\newcommand{\indexPageUL}[1]{\index{#1|underline}}
+\newcommand{\ttize}[1]{{\tt #1}}
+\newcommand{\ttunderline}[1]{\underline{\tt #1}}
+
+\newcommand{\heading}[1]{\par\vspace{2\baselineskip}\noindent #1\par}
+
+\newcommand{\Haskell}{Haskell}
+
+% slightly hacked...
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% File "comment.sty" (by Tom Hofmann, E-mail: wtho@cgch.UUCP)
+% 1989-10-30
+%
+% This File contains the definition of a LaTeX environment "comment"
+% which allows to alternatively print or suppress parts of the document.
+%
+%
+% Usage:
+%
+% - Declare "comment" as documentstyle option or include this file
+% by "\input{comment.sty}"
+% - Embed comments in "\begin{comment}" and "\end{comment}"
+% - To print the document including the comments write "\printcomments"
+% before the first comment. Alternatively, write "\suppresscomments"
+% to print without comments.
+% - The default setting is "\printcomments".
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% (1) Definition of the environment "comment" when notes are
+% to be printed.
+
+% hack here
+% orig: \def\printcomments{\def\comment{}} % "\endcomment" can be missing
+
+\def\printcomments{\def\comment{\par \small {\em Comment:}}} % "\endcomment" can be missing
+
+% (2) Definition of the environment "comment" when notes are not
+% to be printed.
+
+% Make '{' and '}' "other characters" and make '(' and ')'
+% "begingroup" and "endgroup" resp. Thus make it possible
+% to have "\end{comment}" as part of a macro definition.
+
+\begingroup\makeatletter % since the catcodes of '{' and '}'
+\catcode`{=12\relax\catcode`}=12\relax % will change, use \begingroup and
+\catcode`(=1\relax \catcode`)=2\relax % \endgroup instead.
+
+\gdef\suppresscomments(%
+
+% Make '{' and '}' searchable when expanding the macro by giving them
+% the same catcode in the subsequent text as in the macro definition.
+
+ \gdef\comment(\catcode`{=12\relax\catcode`}=12\relax\@NOTE)
+
+% Skip text between "\begin{comment}" and "\end{comment}"
+% (inclusive), but return an "\end{comment}" command to LaTeX for
+% the correct environment handling (see below).
+
+ \long\gdef\@NOTE##1\end{comment}(\@ENDNOTE))
+
+
+\endgroup % End of the enchantment.
+
+% Generate an environment-end command conformable to LaTeX.
+
+{\makeatletter\gdef\@ENDNOTE{\end{comment}}}
+
+\printcomments % This is the default setting.
+
+%========================================================================
+% saves having to put this in all the time
+%\input{makeidx.sty}
+% makeidx.sty 20-Jan-87
+
+\def\see#1#2{{\em see\/} #1}
+\def\printindex{\@input{\jobname.ind}}
+% end of makeidx.sty
+\makeatother
+%========================================================================
+
+%========================================================================
+\makeatletter
+% file tgrind.sty
+% NB: nuke line numbering
+%%%%%%%%%%%
+%NAME: tgrind.sty
+% LaTeX tgrind environment
+
+% Based on Van Jacobson's ``tgrindmac'', a macro package for TeX grinding
+% Our job here is to simplify it quite a bit and make it conform to LaTeX
+
+\newif\ifcomment\newif\ifstring
+\newcount\linecount\newcount\linenext
+\newbox\linesofar
+\newdimen\TBwid
+\newdimen\ts
+\newbox\tbox
+
+\def\tgrind{%
+% Stuff we ignore for right now.
+\let\Head=\@gobble
+\def\File##1,##2,##3{}
+\let\Proc=\@gobble
+\let\ProcCont=\@gobble
+%
+% Each formfeed in the input is replaced by a "\NewPage" macro. If
+% you really want a page break here, define this as "\vfill\eject".
+\def\NewPage{\filbreak\bigskip}
+%
+% Each line of the program text is enclosed by a "\L{...}". We turn
+% each line into an hbox of size hsize. If we saw a procedure name somewhere
+% in the line (i.e., "procbox" is not null), we right justify "procbox"
+% on the line. Every 10 lines we output a small, right justified line number.
+\def\L##1{\par\hbox to\hsize{\CF\strut\global\advance\linecount by1
+##1\hss\linebox}}
+%
+\linecount=0
+\linenext=9
+\def\linebox{\ifnum\linecount>\linenext\global\advance\linenext by10
+% partain: \hbox{\sevrm\the\linecount}\fi}
+% partain2: \hbox{\rm\tiny\the\linecount}\fi}
+\hbox{}\fi}
+%
+% The following weirdness is to deal with tabs. "Pieces" of a line
+% between tabs are output as "\LB{...}". E.g., a line with a tab at
+% column 16 would be output as "\LB{xxx}\Tab{16}\LB{yyy}". (Actually, to
+% reduce the number of characters in the .tex file the \Tab macro
+% supplies the 2nd & subsequent \LB's.) We accumulate the LB stuff in an
+% hbox. When we see a Tab, we grab this hbox (using "\lastbox") and turn
+% it into a box that extends to the tab position. We stash this box in
+% "\linesofar" & use "\everyhbox" to get \linesofar concatenated onto the
+% front of the next piece of the line. (There must be a better way of
+% doing tabs [cf., the Plain.tex tab macros] but I'm not not enough of a
+% TeX wizard to come up with it. Suggestions would be appreciated.)
+\def\LB{\CF\hbox}
+\setbox\linesofar=\null
+\everyhbox={\box\linesofar}
+\def\Tab##1{\setbox\tbox=\lastbox\TBwid=1\wd\tbox\advance\TBwid by 1\ts
+\ifdim\TBwid>##1\ts
+\setbox\linesofar=\hbox{\box\tbox\space}\else
+\setbox\linesofar=\hbox to ##1\ts{\box\tbox\hfil}\fi\LB}
+%
+% A normal space is too thin for code listings. We make spaces & tabs
+% be in "\ts" units (which are the width of a "0" in the current font).
+\setbox\tbox=\hbox{0} \ts=1\wd\tbox \setbox\tbox=\hbox{\hskip 1\ts}
+\def\space{\hskip 1\ts\relax}
+%
+% Font changing stuff for keywords, comments & strings. We put keywords
+% in boldface, comments in text-italic & strings in typewriter. Since
+% we're usually changing the font inside of a \LB macro, we remember the
+% current font in \CF & stick a \CF at the start of each new box.
+% Also, the characters " and ' behave differently in comments than in
+% code, and others behave differently in strings than in code.
+\let\CF=\rm
+\def\K##1{{\bf ##1}} % Keyword
+\def\C{\it\global\let\CF=\it\global\commenttrue\relax} % Comment Start
+\def\CE{\rm\global\let\CF=\rm\global\commentfalse\relax}% Comment End
+\def\S{\tt\global\let\CF=\tt\global\stringtrue\relax} % String Start
+\def\SE{\rm\global\let\CF=\rm\global\stringfalse\relax} % String End
+%
+% Special characters.
+\def\{{\ifmmode\lbrace\else\ifstring{\char'173}\else$\lbrace$\fi\fi}
+\def\}{\ifmmode\rbrace\else\ifstring{\char'175}\else$\rbrace$\fi\fi}
+\def\!{\ifmmode\backslash\else\ifstring{\char'134}\else$\backslash$\fi\fi}
+\def\|{\ifmmode|\else\ifstring{\char'174}\else$|$\fi\fi}
+\def\<{\ifmmode<\else\ifstring<\else$<$\fi\fi}
+\def\>{\ifmmode>\else\ifstring>\else$>$\fi\fi}
+\def\/{\ifmmode/\else\ifstring/\else$/$\fi\fi}
+\def\-{\ifmmode-\else\ifstring-\else$-$\fi\fi}
+\def\_{\ifstring{\char'137}\else\underbar{\ }\fi}
+\def\&{{\char'046}}
+\def\#{{\char'043}}
+\def\%{{\char'045}}
+\def\~{{\char'176}}
+\def\"{\ifcomment''\else{\tt\char'042}\fi}
+\def\'{\ifcomment'\else{\tt\char'047}\fi}
+\def\^{{\char'136}}
+\def\${{\rm\char'044}}
+%
+\raggedright\obeyspaces%\let =\space%
+}
+
+% \tagrind*[FLOAT]{FILE}{CAPTION}{LABEL}
+% * optional
+% FLOAT float options
+% FILE reads LaTeXgrind input in file FILE
+% CAPTION for list of figures
+% LABEL for \ref and \pageref
+\def\tagrind{\@ifstar{\@stagrind}{\@tagrind}}
+
+\def\@tagrind{\@ifnextchar[{\@@tagrind}{\@@tagrind[t]}}
+\def\@stagrind{\@ifnextchar[{\@@stagrind}{\@@stagrind[t]}}
+
+\def\@@tagrind[#1]#2#3#4{%
+ \begin{figure}[#1]
+ \hrule
+ \vskip .5\baselineskip
+ \begin{minipage}\columnwidth\small
+ \begin{tgrind}
+ \input #2\relax
+ \end{tgrind}
+ \end{minipage}
+ \vskip .5\baselineskip plus .5\baselineskip
+ \begingroup
+ \setbox\z@=\hbox{#4}%
+ \ifdim\wd\z@>\z@
+ \caption{#3}%
+ \label{#4}%
+ \else
+ \captcont{#3}%
+ \fi
+ \endgroup
+ \vskip 2pt
+ \hrule
+ \end{figure}
+}
+
+\def\@@stagrind[#1]#2#3#4{%
+ \begin{figure*}[#1]
+ \hrule
+ \vskip .5\baselineskip
+ \begin{minipage}\textwidth\small
+ \begin{tgrind}
+ \input #2\relax
+ \end{tgrind}
+ \end{minipage}
+ \vskip .5\baselineskip plus .5\baselineskip
+ \begingroup
+ \setbox\z@=\hbox{#4}%
+ \ifdim\wd\z@>\z@
+ \caption{#3}%
+ \label{#4}%
+ \else
+ \captcont{#3}%
+ \fi
+ \endgroup
+ \vskip 2pt
+ \hrule
+ \end{figure*}
+}
+
+
+\def\tgrindfile#1{%
+ \par\addvspace{0.1in}
+ \hrule
+ \vskip .5\baselineskip
+ \begin{footnotesize}
+ \begin{tgrind}
+ \input #1\relax
+ \end{tgrind}
+ \end{footnotesize}
+ \vskip .5\baselineskip
+ \hrule
+ \addvspace{0.1in}
+}
+% end of tgrind.sty
+\makeatother
+%========================================================================
+
+%========================================================================
+% changebar.sty
+\makeatletter
+
+%% This is file `changebar.sty' generated
+%% on <1992/1/6> with the docstrip utility (v1.1k).
+%%
+%% The original source file was `changebar.doc'.
+%% Included modules: `changebar'.
+%%
+%% IMPORTANT NOTICE:
+%% You are not allowed to distribute this file.
+%% For distribution of the original source see
+%% the copyright notice in the file `changebar.doc'.
+%%
+\def\fileversion{v3.0-test}
+\def\filedate{6 Nov 91}
+\def\docdate{6 Nov 91}
+%% \CheckSum{798}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\wlog{Document style option `changebar', \fileversion\space<\filedate>}
+\chardef\atcatcode=\catcode`\@
+\catcode`\@=11\relax
+\def\cb@maxpoint{80}
+\def\cb@minpoint{1}
+\def\cb@nil{0}
+\newcount\cb@nextpoint
+\cb@nextpoint=\cb@minpoint
+\newcount\cb@currentpoint
+\newcount\cb@page
+\newcount\cb@pagecount
+\cb@pagecount=0
+\newif\ifouterbars \outerbarsfalse
+\newdimen\cb@odd
+\newdimen\cb@even
+\def\cb@positions{%
+ \global\cb@odd =\hoffset
+ \global\advance\cb@odd by \oddsidemargin
+ \ifouterbars
+ \global\advance\cb@odd by \textwidth
+ \global\advance\cb@odd by \changebarsep
+ \else
+ \global\advance\cb@odd by -\changebarsep
+ \fi
+ \global\cb@even =\hoffset
+ \global\advance\cb@even by \evensidemargin
+ \if@twoside
+ \ifouterbars
+ \global\advance\cb@even by -\changebarsep
+ \else
+ \global\advance\cb@even by \textwidth
+ \global\advance\cb@even by \changebarsep
+ \fi
+ \else
+ \ifouterbars
+ \global\advance\cb@even by \textwidth
+ \global\advance\cb@even by \changebarsep
+ \else
+ \fi
+ \global\advance\cb@even by -\changebarsep
+ \fi}
+{\catcode`\p=12\catcode`\t=12 \gdef\cb@removedim#1pt{#1}}
+\def\driver#1{%
+ \bgroup\edef\next{\def\noexpand\tempa{#1}}%
+ \uppercase\expandafter{\next}%
+ \def\LN{DVITOLN03}%
+ \def\DVItoPS{DVITOPS}%
+ \def\DVIPS{DVIPS}%
+ \def\emTeX{EMTEX}%
+ \global\chardef\cb@driver@setup=0
+ \ifx\tempa\LN \global\chardef\cb@driver@setup=0\fi
+ \ifx\tempa\DVItoPS \global\chardef\cb@driver@setup=1\fi
+ \ifx\tempa\DVIPS \global\chardef\cb@driver@setup=2\fi
+ \ifx\tempa\emTeX \global\chardef\cb@driver@setup=3\fi
+ \egroup}
+{\def\do{\noexpand\do\noexpand}
+ \xdef\@preamblecmds{\@preamblecmds \do\driver}
+}
+\def\cb@setup@specials{%
+\ifcase\cb@driver@setup
+ \def\cb@defpoint##1##2{\special{ln03:defpoint \the##1(\the##2,)}}
+ \def\cb@connect##1##2##3{%
+ \special{ln03:connect \the##1\space\space \the##2\space \the##3}}
+ \def\cb@resetpoints{%
+ \special{ln03:resetpoints \cb@minpoint \space\cb@maxpoint}}
+\or
+ \def\cb@defpoint##1##2{%
+ \special{dvitops: inline
+ \expandafter\cb@removedim\the##2\space 6.5536 mul\space
+ /CBarX\the##1\space exch def currentpoint exch pop
+ /CBarY\the##1\space exch def}}
+ \def\cb@connect##1##2##3{%
+ \special{dvitops: inline
+ gsave \thechangebargrey\space 100 div setgray
+ \expandafter\cb@removedim\the##3\space 6.5536 mul\space
+ CBarX\the##1\space\space CBarY\the##1\space\space moveto
+ CBarX\the##2\space\space CBarY\the##2\space\space lineto
+ stroke grestore}}
+ \let\cb@resetpoints\relax
+\or
+ \def\cb@defpoint##1##2{%
+ \special{ps:
+ \expandafter\cb@removedim\the##2\space 4.096 mul\space
+ Resolution\space mul\space 300\space div\space
+ /CBarX\the##1\space exch def currentpoint exch pop
+ /CBarY\the##1\space exch def}}
+ \def\cb@connect##1##2##3{%
+ \special{ps:
+ gsave \thechangebargrey\space 100 div setgray
+ \expandafter\cb@removedim\the##3\space 4.096 mul\space
+ Resolution\space mul\space 300\space div\space
+ setlinewidth
+ CBarX\the##1\space\space CBarY\the##1\space\space moveto
+ CBarX\the##2\space\space CBarY\the##2\space\space lineto
+ stroke grestore}}
+ \let\cb@resetpoints\relax
+\or
+ \typeout{Changebar Warning: changebars only supported for v1.5+ of dvidrv}%
+ \def\cb@defpoint##1##2{\special{em:point \the##1,\the##2}}
+ \def\cb@connect##1##2##3{\special{em:line \the##1,\the##2,\the##3}}
+ \let\cb@resetpoints\relax
+\else
+ \typeout{Changebar Warning: changebars not supported in unknown setup}
+ \def\cb@defpoint##1##2{}
+ \def\cb@connect##1##2##3{}
+ \let\cb@resetpoints\relax
+\fi
+\global\let\cb@setup@specials\relax}
+\def\cbstart{\@ifnextchar [{\cb@start}{\cb@start[\changebarwidth]}}
+\def\cbend{\cb@end}
+\def\cbdelete{\@ifnextchar [{\cb@delete}{\cb@delete[\deletebarwidth]}}
+\def\cb@delete[#1]{\vbox to 0pt{\vss\cb@start[#1]\vskip #1\cb@end}}
+\def\changebar{\@ifnextchar [{\cb@start}{\cb@start[\changebarwidth]}}%
+\def\endchangebar{\cb@end}
+\def\nochangebars{\def\cb@start[##1]{}%
+ \def\cb@delete[##1]{}%
+ \let\cb@end\relax}
+\newlength{\changebarwidth}
+\setlength{\changebarwidth}{2pt}
+\newlength{\deletebarwidth}
+\setlength{\deletebarwidth}{4pt}
+\newlength{\changebarsep}
+\setlength{\changebarsep}{30pt}
+\newcounter{changebargrey}
+\setcounter{changebargrey}{65}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\cb@start[#1]{\cb@currentpoint=\cb@nextpoint
+ \@tempdima=#1\relax % for \cb@push
+ \cb@push\cb@currentlist
+ \ifvmode \cb@setBeginPoint\cb@currentpoint
+ \else \vbox to 0pt{\vskip -\ht\strutbox %jump up a line to
+ \cb@setBeginPoint\cb@currentpoint %set point
+ \vskip \ht\strutbox}\fi
+ \cb@writeAux\cb@advancePoint}
+\def\cb@advancePoint{%
+ \global\advance\cb@nextpoint by 2\relax
+ \ifnum\cb@nextpoint>\cb@maxpoint
+ \global\cb@nextpoint=\cb@minpoint\relax
+ \fi}
+\def\cb@end{%
+ \cb@pop\cb@currentlist
+ \ifnum\cb@currentpoint=\cb@nil
+ \typeout{Changebar Warning: Badly nested changebars;
+ Expect erroneous results}%
+ \else
+ \cb@setEndPoint\cb@currentpoint
+ \advance\cb@currentpoint by1\cb@writeAux
+ \fi}
+\def\cb@setBeginPoint#1{%
+ \ifodd\cb@pagecount
+ \cb@defpoint{#1}{\cb@even}%
+ \else
+ \cb@defpoint{#1}{\cb@odd}%
+ \fi}
+\def\cb@setEndPoint#1{%
+ \@tempcnta=#1\advance\@tempcnta by1\relax
+ \ifodd\cb@pagecount
+ \cb@defpoint{\@tempcnta}{\cb@even}%
+ \else
+ \cb@defpoint{\@tempcnta}{\cb@odd}%
+ \fi
+ \cb@connect{#1}{\@tempcnta}{\@tempdima}}%
+\def\cb@writeAux{%
+ \if@filesw
+ \begingroup
+ \edef\point{\the\cb@currentpoint}%
+ \edef\level{\the\@tempdima}%
+ \let\the=0%
+ \edef\cb@temp{\write\@auxout
+ {\string\cb@barpoint{\point}{\the\cb@pagecount}{\level}}}%
+ \cb@temp
+ \endgroup
+ \fi}
+\let\cb@makecol=\@makecol
+\def\@makecol{%
+ \setbox\@cclv=\vbox{\cb@resetpoints\cb@beginSaves\unvbox\@cclv}%
+ \gdef\cb@beginSaves{}
+ \global\advance\cb@pagecount by 1%
+ \cb@buildActive\cb@processActive
+ \cb@makecol}
+\def\cb@processActive{%
+ \cb@pop\cb@spanlist
+ \ifnum\cb@currentpoint=\cb@nil
+ \else
+ \setbox\@cclv=\vbox{\unvbox\@cclv\advance\cb@pagecount by -1%
+ \cb@setEndPoint\cb@currentpoint}%
+ \cb@saveBeginPoint\cb@currentpoint
+ \cb@push\cb@history
+ \cb@processActive
+ \fi}
+\def\cb@saveBeginPoint#1{%
+ \ifodd\cb@pagecount
+ \xdef\cb@beginSaves{\cb@defpoint{#1}{\cb@even}\cb@beginSaves}%
+ \else
+ \xdef\cb@beginSaves{\cb@defpoint{#1}{\cb@odd}\cb@beginSaves}%
+ \fi}
+\def\cb@beginSaves{} % initially empty
+\def\cb@buildActive{\cb@initlist\cb@spanlist\cb@pushNextActive}
+\def\cb@pushNextActive{%
+ \cb@pop\cb@history
+ \ifnum\cb@currentpoint=\cb@nil
+ \else
+ \ifnum\cb@page>\cb@pagecount
+ \cb@push\cb@history
+ \else
+ \ifodd\cb@currentpoint
+ \cb@push\cb@spanlist
+ \else
+ \cb@pop\cb@spanlist
+ \fi
+ \cb@pushNextActive
+ \fi
+ \fi}
+\def\cb@initlist#1{\xdef#1{}}
+\cb@initlist\cb@history % the history list; initially empty
+\cb@initlist\cb@spanlist % list of bars spanning current page
+\cb@initlist\cb@currentlist % used to implement nesting without using
+
+\newwrite\cb@write % file for history list
+\newread\cb@read
+\immediate\openout\cb@write=\jobname.cb % open for building of history list
+\def\cb@pop#1{%
+ \ifx #1\cb@history
+ \ifeof\cb@read
+ \else
+ {\endlinechar=-1\read\cb@read to\@temp
+ \xdef\cb@history{\cb@history\@temp}%
+ }%
+ \fi
+ \fi
+ \ifx#1\@empty
+ \cb@currentpoint=\cb@nil\cb@page=0%
+ \else
+ \expandafter\cb@carcdr#1e#1%
+ \fi}
+\def\cb@carcdr#1n#2p#3l#4e#5{%
+ \cb@currentpoint=#1\cb@page=#2\@tempdima=#3\xdef#5{#4}}
+\def\cb@push#1{%
+ \xdef#1{\the\cb@currentpoint n\the\cb@page p\the\@tempdima l#1}}
+\def\cb@barpoint#1#2#3{\immediate\write\cb@write{#1n#2p#3l}}
+\let\cb@document=\document
+\def\document{\cb@document
+ \cb@setup@specials
+ \cb@positions
+ \immediate\closeout\cb@write
+ \immediate\openin\cb@read=\jobname.cb}
+\let\cb@enddocument\enddocument
+\def\enddocument{\clearpage\cb@initlist\cb@history
+ \immediate\closein\cb@read\immediate\openin\cb@read=\jobname.cb%
+ \let\cb@barpoint=\cb@checkHistory\cb@enddocument}
+\def\cb@checkHistory#1#2#3{\cb@pop\cb@history
+ \ifnum #1=\cb@currentpoint
+ \ifnum #2=\cb@page % do nothing
+ \else \cb@error % page numbers mismatched
+ \fi
+ \else \cb@error % point numbers mismatched
+ \fi}
+\def\cb@error{%
+ \message{Changebar Warning: Changebar info has changed. %
+ Rerun to get right.}
+ \gdef\cb@checkHistory##1##2##3{}%
+ \let\cb@barpoint=\cb@checkHistory}
+\let\cb@endfloat=\end@float
+\def\end@float{%
+ \cb@pop\cb@currentlist
+ \ifnum\cb@currentpoint=\cb@nil
+ \else
+ \cb@push\cb@currentlist
+ \global\@tempdima=\@tempdima
+ \egroup
+ \global\setbox\@currbox=%
+ \vbox\bgroup\cb@start[\@tempdima]\unvbox\@currbox\cb@end
+ \fi
+ \cb@endfloat}
+\let\endfigure=\end@float % need to rebind these to new def
+\let\endtable=\end@float
+\let\cb@footnote=\@footnotetext
+\long\def\@footnotetext#1{%
+ \cb@pop\cb@currentlist
+ \ifnum\cb@currentpoint=\cb@nil
+ \cb@footnote{#1}
+ \else
+ \cb@push\cb@currentlist
+ \edef\cb@temp{\the\@tempdima}%
+ \cb@footnote{\cb@start[\cb@temp]#1\cb@end}%
+ \fi}
+\let\cb@mpfootnote=\@mpfootnotetext
+\long\def\@mpfootnotetext#1{%
+ \cb@pop\cb@currentlist
+ \ifnum\cb@currentpoint=\cb@nil
+ \cb@mpfootnote{#1}
+ \else
+ \cb@push\cb@currentlist
+ \edef\cb@temp{\the\@tempdima}%
+ \cb@mpfootnote{\cb@start[\cb@temp]#1\cb@end}%
+ \fi}
+\catcode`\@=\atcatcode \let\atcatcode\relax
+%\endinput
+%%
+%% End of file `changebar.sty'.
+%
+% end of changebar.sty; now we configure it:
+%
+% partain:
+\driver{DVIPS}
+% want black, thin lines
+\setlength{\changebarwidth}{0.2pt}
+\setcounter{changebargrey}{0}
+%
+\makeatother
+%========================================================================
+
+%========================================================================
+\makeatletter
+
+% Olin Shiver's code.sty
+% partain: the stuff actually used is defined immediately afterwards
+%--------
+% code.sty: -*- latex -*-
+% Latex macros for a "weak" verbatim mode.
+% -- like verbatim, except \, {, and } have their usual meanings.
+
+% Environments: code, tightcode, codeaux, codebox, centercode
+% Commands: \dcd, \cddollar, \cdmath, \cd, \codeallowbreaks, \codeskip, \^
+% Already defined in LaTeX, but of some relevance: \#, \$, \%, \&, \_, \{, \}
+
+% Changelog at the end of the file.
+
+% These commands give you an environment, code, that is like verbatim
+% except that you can still insert commands in the middle of the environment:
+% \begin{code}
+% for(x=1; x<loop_bound; x++)
+% y += x^3; /* {\em Add in {\tt x} cubed} */
+% \end{code}
+%
+% All characters are ordinary except \{}. To get \{} in your text,
+% you use the commands \\, \{, and \}.
+
+% These macros mess with the definition of the special chars (e.g., ^_~%).
+% The characters \{} are left alone, so you can still have embedded commands:
+% \begin{code} f(a,b,\ldots,y,z) \end{code}
+% However, if your embedded commands use the formerly-special chars, as in
+% \begin{code} x := x+1 /* \mbox{\em This is $y^3$} */ \end{code}
+% then you lose. The $ and ^ chars are scanned in as non-specials,
+% so they don't work. If the chars are scanned *outside* the code env,
+% then you have no problem:
+% \def\ycube{$y^3$}
+% \begin{code} x := x+1 /* {\em This is \ycube} */ \end{code}
+% If you must put special chars inside the code env, you do it by
+% prefixing them with the special \dcd ("decode") command, that
+% reverts the chars to back to special status:
+% \begin{code} x := x+1 /* {\dcd\em This is $y^3$} */ \end{code}
+% \dcd's scope is bounded by its enclosing braces. It is only defined within
+% the code env. You can also turn on just $ with the \cddollar command;
+% you can turn on just $^_ with the \cdmath command. See below.
+%
+% Alternatively, just use \(...\) for $...$, \sp for ^, and \sb for _.
+
+% WARNING:
+% Like \verb, you cannot put a \cd{...} inside an argument to a macro
+% or a command. If you try, for example,
+% \mbox{\cd{$x^y$}}
+% you will lose. That is because the text "\cd{$x^y$}" gets read in
+% as \mbox's argument before the \cd executes. But the \cd has to
+% have a chance to run before LaTeX ever reads the $x^y$ so it can
+% turn off the specialness of $ and ^. So, \cd has to appear at
+% top level, not inside an argument. Similarly, you can't have
+% a \cd or a \code inside a macro (Although you could use \gdef to
+% define a macro *inside* a \cd, which you could then use outside.
+% Don't worry about this if you don't understand it.)
+
+% BUG: In the codebox env, the effect of a \dcd, \cddollar, or \cdmath
+% command is reset at the end of each line. This can be hacked by
+% messing with the \halign's preamble, if you feel up to it.
+
+% Useage note: the initial newline after the \begin{code} or
+% \begin{codebox} is eaten, but the last newline is not.
+% So,
+% \begin{code}
+% foo
+% bar
+% \end{code}
+% leaves one more blank line after bar than does
+% \begin{code}
+% foo
+% bar\end{code}
+% Moral: get in the habit of terminating code envs without a newline
+% (as in the second example).
+%
+
+% All this stuff tweaks the meaning of space, tab, and newline.
+%===============================================================================
+% \cd@obeyspaces
+% Turns all spaces into non-breakable spaces.
+% Note: this is like \@vobeyspaces except without spurious space in defn.
+% @xobeysp is basically a space; it's defined in latex.tex.
+%
+{\catcode`\ =\active\gdef\cd@obeyspaces{\catcode`\ =\active\let =\@xobeysp}}
+
+
+
+% \cd@obeytabs
+% Turns all tabs into 8 non-breakable spaces (which is bogus).
+%
+{\catcode`\^^I=\active %
+ \gdef\cd@obeytabs{\catcode`\^^I=\active\let^^I=\cd@tab}}
+
+\def\cd@tab{\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp}
+
+
+
+% \cd@obeylines
+% Turns all cr's into linebreaks. Pagebreaks are not permitted between lines.
+% This is copied from lplain.tex's \obeylines, with the cr def'n changed.
+%
+{\catcode`\^^M=\active % these lines must end with %
+ \gdef\cd@obeylines{\catcode`\^^M=\active\let^^M=\cd@cr}}
+
+% What ^M turns into. This def'n keeps blank lines from being compressed out.
+\def\cd@cr{\par\penalty10000\leavevmode} % TeX magicness
+%\def\cd@cr{\par\penalty10000\mbox{}} % LaTeX
+
+
+% \codeallowbreaks
+% Same as \cd@obeylines, except pagebreaks are allowed.
+% Put this command inside a code env to allow pagebreaks.
+
+{\catcode`\^^M=\active % these lines must end with %
+ \gdef\codeallowbreaks{\catcode`\^^M\active\let^^M\cd@crbr}}
+
+%\def\cd@crbr{\leavevmode\endgraf} % What ^M turns into.
+%partain:
+\def\cd@crbr{\par\leavevmode} % What ^M turns into.
+
+
+% \cd@obeycrsp
+% Turns cr's into non-breakable spaces. Used by \cd.
+
+{\catcode`\^^M=\active % these lines must end with %
+ \gdef\cd@obeycrsp{\catcode`\^^M=\active\let^^M=\@xobeysp}}
+
+% =============================================================================
+
+% Set up code environment, in which most of the common special characters
+% appearing in code are treated verbatim, namely: $&#^_~%
+% \ { } are still enabled so that macros can be called in this
+% environment. Use \\, \{, and \} to use these characters verbatim
+% in this environment.
+%
+% Inside a group, you can make
+% all the hacked chars special with the \dcd command
+% $ special with the \cddollar command
+% $^_ special with the \cdmath command.
+% If you have a bunch of math $..$'s in your code env, then a global \cddollar
+% or \cdmath at the beginning of the env can save a lot of trouble.
+% When chars are special (e.g., after a \dcd), you can still get #$%&_{} with
+% \#, \$, \%, \&, \_, \{, and \} -- this is standard LaTeX.
+% Additionally, \\ gives \ inside the code env, and when \cdmath
+% makes ^ special, it also defines \^ to give ^.
+
+%The hacked characters can be made special again
+% within a group by using the \dcd command.
+
+% Note: this environment allows no breaking of lines whatsoever; not
+% at spaces or hypens. To arrange for a break use the standard \- command,
+% or a \discretionary{}{}{} which breaks, but inserts nothing. This is useful,
+% for example for allowing hypenated identifiers to be broken, e.g.
+% \def\={\discretionary{}{}{}} %optional break
+% FOO-\=BAR.
+
+\def\setupcode{\parsep=0pt\parindent=0pt%
+ \tt\frenchspacing\catcode``=13\@noligs%
+ \def\\{\char`\\}%
+ \let\dcd=\cd@dcd\let\cddollar=\cd@dollarspecial\let\cdmath=\cd@mathspecial%
+ \@makeother\$\@makeother\&\@makeother\#%
+ \@makeother\^\@makeother\_\@makeother\~%
+ \@makeother\%\cd@obeytabs\cd@obeyspaces}
+% other: $&#^_~%
+% left special: \{}
+% unnecessary: @`'"
+
+
+%% codebox, centercode
+%%=============================================================================
+%% The codebox env makes a box exactly as wide as it needs to be
+%% (i.e., as wide as the longest line of code is). This is useful
+%% if you want to center a chunk of code, or flush it right, or
+%% something like that. The optional argument to the environment,
+%% [t], [c], or [b], specifies how to vertically align the codebox,
+%% just as with arrays or other boxes. Default is [c].
+
+%% Must be a newline immediately after "\begin{codebox}[t]"!
+
+{\catcode`\^^M=\active % these lines must end with %
+ \gdef\cd@obeycr{\catcode`\^^M=\active\let^^M=\cr}}
+
+% If there is a [<letter>] option, then the following newline will
+% be read *after* ^M is bound to \cr, so we're cool. If there isn't
+% an option given (i.e., default to [c]), then the @\ifnextchar will
+% gobble up the newline as it gobbles whitespace. So we insert the
+% \cr explicitly. Isn't TeX fun?
+\def\codebox{\leavevmode\@ifnextchar[{\@codebox}{\@codebox[c]\cr}} %]
+
+\def\@codebox[#1]%
+ {\hbox\bgroup$\if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi\bgroup%
+ \tabskip\z@\setupcode\cd@obeycr% just before cd@obey
+ \halign\bgroup##\hfil\span}
+
+\def\endcodebox{\crcr\egroup\egroup\m@th$\egroup}
+
+% Center the box on the page:
+\newenvironment{centercode}%
+ {\begin{center}\begin{codebox}[c]}%
+ {\end{codebox}\end{center}}
+
+
+%% code, codeaux, tightcode
+%%=============================================================================
+%% Code environment as described above. Lines are kept on one page.
+%% This actually works by setting a huge penalty for breaking
+%% between lines of code. Code is indented same as other displayed paras.
+%% Note: to increase left margin, use \begin{codeaux}{\leftmargin=1in}.
+
+% To allow pagebreaks, say \codeallowbreaks immediately inside the env.
+% You can allow breaks at specific lines with a \pagebreak form.
+
+%% N.B.: The \global\@ignoretrue command must be performed just inside
+%% the *last* \end{...} before the following text. If not, you will
+%% get an extra space on the following line. Blech.
+
+%% This environment takes two arguments.
+%% The second, required argument is the \list parameters to override the
+%% \@listi... defaults.
+%% - Usefully set by clients: \topsep \leftmargin
+%% - Possible, but less useful: \partopsep
+%% The first, optional argument is the extra \parskip glue that you get around
+%% \list environments. It defaults to the value of \parskip.
+\def\codeaux{\@ifnextchar[{\@codeaux}{\@codeaux[\parskip]}} %]
+\def\@codeaux[#1]#2{%
+ \bgroup\parskip#1%
+ \begin{list}{}%
+ {\parsep\z@\rightskip\z@\listparindent\z@\itemindent\z@#2}%
+ \item[]\setupcode\cd@obeylines}%
+\def\endcodeaux{\end{list}\leavevmode\egroup\ignorespaces\global\@ignoretrue}
+
+%% Code env is codeaux with the default margin and spacing \list params:
+\def\code{\codeaux{}} \let\endcode=\endcodeaux
+
+%% Like code, but with no extra vertical space above and below.
+\def\tightcode{\codeaux[=0pt]{\topsep\z@}}%
+\let\endtightcode\endcodeaux
+% {\vspace{-1\parskip}\begin{codeaux}{\partopsep\z@\topsep\z@}}%
+% {\end{codeaux}\vspace{-1\parskip}}
+
+
+
+% Reasonable separation between lines of code
+\newcommand{\codeskip}{\penalty0\vspace{2ex}}
+
+
+% \cd is used to build a code environment in the middle of text.
+% Note: only difference from display code is that cr's are taken
+% as unbreakable spaces instead of linebreaks.
+
+\def\cd{\leavevmode\begingroup\ifmmode\let\startcode=\startmcode\else%
+ \let\startcode\starttcode\fi%
+ \setupcode\cd@obeycrsp\startcode}
+
+\def\starttcode#1{#1\endgroup}
+\def\startmcode#1{\hbox{#1}\endgroup}
+
+
+% Restore $&#^_~% to their normal catcodes
+% Define \^ to give the ^ char.
+% \dcd points to this guy inside a code env.
+\def\cd@dcd{\catcode`\$=3\catcode`\&=4\catcode`\#=6\catcode`\^=7%
+ \catcode`\_=8\catcode`\~=13\catcode`\%=14\def\^{\char`\^}}
+
+% Selectively enable $, and $^_ as special.
+% \cd@mathspecial also defines \^ give the ^ char.
+% \cddollar and \cdmath point to these guys inside a code env.
+\def\cd@dollarspecial{\catcode`\$=3}
+\def\cd@mathspecial{\catcode`\$=3\catcode`\^=7\catcode`\_=8%
+ \def\^{\char`\^}}
+
+
+% Change log:
+% Started off as some macros found in C. Rich's library.
+% Olin 1/90:
+% Removed \makeatletter, \makeatother's -- they shouldn't be there,
+% because style option files are read with makeatletter. The terminal
+% makeatother screwed things up for the following style options.
+% Olin 3/91:
+% Rewritten.
+% - Changed things so blank lines don't get compressed out (the \leavevmove
+% in \cd@cr and \cd@crwb).
+% - Changed names to somewhat less horrible choices.
+% - Added lots of doc, so casual hackers can more easily mess with all this.
+% - Removed `'"@ from the set of hacked chars, since they are already
+% non-special.
+% - Removed the bigcode env, which effect can be had with the \codeallowbreaks
+% command.
+% - Removed the \@noligs command, since it's already defined in latex.tex.
+% - Win big with the new \dcd, \cddollar, and \cdmath commands.
+% - Now, *only* the chars \{} are special inside the code env. If you need
+% more, use the \dcd command inside a group.
+% - \cd now works inside math mode. (But if you use it in a superscript,
+% it still comes out full size. You must explicitly put a \scriptsize\tt
+% inside the \cd: $x^{\cd{\scriptsize\tt...}}$. A \leavevmode was added
+% so that if you begin a paragraph with a \cd{...}, TeX realises you
+% are starting a paragraph.
+% - Added the codebox env. Tricky bit involving the first line hacked
+% with help from David Long.
+
+% end of code.sty
+%
+% partain: things actually used
+%% verbcode env is like tightcode:
+%\def\verbcode{\codeaux[=0pt]{\topsep\z@\parskip\z@\leftmargin\litcodeindent}} \let\endverbcode=\endcodeaux
+%\def\verbcode{\codeaux{\leftmargin\litcodeindent\cbstart}}%
+\def\verbcode{%
+ \bgroup\parskip\parskip%
+ \begin{list}{}%
+ {\parsep\z@\rightskip\z@\listparindent\z@\itemindent\z@\leftmargin\litcodeindent}%
+ \item[]\setupcode\cd@obeylines\cbstart}%
+\def\endverbcode{\cbend\end{list}\leavevmode\egroup\ignorespaces\global\@ignoretrue}
+%
+\def\verbtext{\codeaux{\leftmargin\litcodeindent}} \let\endverbtext=\endcodeaux
+%
+\makeatother
+%========================================================================
diff --git a/web/glasgow/lit2x-0.16/literate/lit2pgm.BOOT b/web/glasgow/lit2x-0.16/literate/lit2pgm.BOOT
new file mode 100644
index 0000000000..b2dea81d65
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit2pgm.BOOT
@@ -0,0 +1,385 @@
+eval "exec perl -S $0 $*"
+ if $running_under_some_random_shell;
+#
+#############
+# magic version for booting...
+###########
+# line 27 "lit2stuff.lprl"
+$Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/;
+
+# an initial -A<name> option overrides the name
+if ($#ARGV >= 0 && $ARGV[0] =~ /^-A(lit2)(pgm|texi|latex)$/) {
+ $Pgm = $1.$2;
+ shift(@ARGV);
+}
+$Lit2pgm = ($Pgm eq 'lit2pgm') ? 1 : 0;
+$Lit2latex = ($Pgm eq 'lit2latex') ? 1 : 0;
+$Lit2texi = ($Pgm eq 'lit2texi') ? 1 : 0;
+$Lit2depend = ($Pgm eq 'mkdependlit') ? 1 : 0;
+$Lit2changelog = ($Pgm eq 'lit2changelog') ? 1 : 0;
+die "$Pgm: must be invoked as lit2pgm, lit2texi, lit2latex, mkdependlit, or lit2changelog (or use -A<name>)\n"
+ if (!($Lit2pgm || $Lit2latex || $Lit2texi || $Lit2depend || $Lit2changelog));
+
+# $Lit2what will be set after we know $Quick_lit2pgm
+
+$Status = 0; # just used for exit() status
+# line 53 "lit2stuff.lprl"
+do 'getopts.pl' || die "Giant error 'do'ing getopts.pl: $@";
+$Usage = "usage: $Pgm ".
+ '[-i input-file] '.
+ '[-I LITINPUTS-path-additions] '.
+ '[-o output-file] ';
+$Usage .= '[-cdnqv] '.
+ '[-r ribbons] '.
+ "[input-file]\n" if $Lit2pgm;
+$Usage .= '[-cdLnOSv] '.
+ '[-N infofilename] '.
+ '[-[lx] language] '.
+ '[-s stop-list-file] '.
+ "[input-file]\n" if $Lit2texi;
+$Usage .= '[-cdnOSv] '.
+ '[-g node-name] '.
+ '[-[lptx] language] '.
+ '[-s stop-list-file] '.
+ "[input-file]\n" if $Lit2latex;
+$Usage .= '[-dv] '.
+ "[input-file]\n" if $Lit2depend;
+$Usage .= '[-dnv] '.
+ "[input-file]\n" if $Lit2changelog;
+
+if ( ($Lit2pgm && ! &Getopts('cdH:I:i:no:qr:v'))
+ || ($Lit2texi && ! &Getopts('cdH:I:i:Ll:nN:Oo:Ss:vx:'))
+ || ($Lit2latex && ! &Getopts('cdg:H:I:i:l:no:Op:Ss:t:vx:'))
+ || ($Lit2depend && ! &Getopts('dH:I:i:o:v'))
+ || ($Lit2changelog && ! &Getopts('dH:I:i:no:v'))) {
+ print STDERR $Usage;
+ exit 1;
+} elsif ($#ARGV > 0) {
+ print STDERR "$Pgm: cannot have more than one input file: @ARGV \n";
+ print STDERR $Usage;
+ exit 1;
+}
+# SHARED OPTIONS
+$Debugging = ($opt_d) ? 1 : 0;
+$Verbose = ($Debugging | $opt_v) ? 1 : 0;
+$Input_file = ($opt_i) ? $opt_i : '';
+# -o <output file> handled after deciding if linking
+
+$Litinputs = '.';
+$Litinputs_adds = ($opt_I) ? $opt_I : '';
+$Litinputs = "$Litinputs_adds:$Litinputs" if $Litinputs && $Litinputs_adds;
+
+# where all the assisting code is found (HARDWIRED)
+if ($opt_H) {
+ # no error checking; you get what you deserve
+ ($LIB_ARCH_DIR,$LIB_DIR) = split(/:/,$opt_H);
+} else {
+# boot changes...
+ $LIB_ARCH_DIR = '.';
+ $LIB_DIR = '.';
+}
+unshift(@INC, $LIB_DIR); # adding to; for .prl libraries sucked in at runtime
+#
+# now the (derived) names of all the helpers
+$Lit_inputter = "$LIB_DIR/lit-inputter";
+$Lit_deatify = "$LIB_ARCH_DIR/lit-deatify";
+$Lit_verb2latex = "$LIB_ARCH_DIR/lit-verb2latex";
+
+# finish knowing myself; must agree with lit-deatify.llex
+# boot change
+$Quick_lit2pgm = 1; # ($opt_q) ? 1 : 0;
+$Lit2what = 1; # if $Quick_lit2pgm;
+
+# LESS SHARED OPTIONS
+$Grab_node = ($opt_g) ? $opt_g : 'Top';
+$Infofilename = ($opt_N) ? $opt_N : ''; # see do_setfilename
+$Follow_inputs = ($opt_n) ? 1 : 0;
+$Show_node_owner= ($opt_O) ? 1 : 0;
+$Opt_node_links = ($opt_L) ? 1 : 0;
+$Standalone_doc = ($opt_S) ? 1 : 0;
+
+$Stoplist_file = ($opt_s) ? $opt_s : '';
+# for now, stop lists are simply words to be ignored
+if ($Stoplist_file) {
+ if ( ! -f $Stoplist_file) {
+ &not_OK('','',"stop-list file does not exist: $Stoplist_file\n");
+ } else {
+ open(STOPF,"<$Stoplist_file") || die "Can't open file: $Stoplist_file\n";
+ while (<STOPF>) {
+ chop;
+ $IGNORE_WD{$_} = 1; # no questions asked...
+ }
+ close(STOPF);
+ }
+}
+
+$Ribbons_to_get = ($opt_r) ? $opt_r : 'main';
+$Ribbons_to_get =~ s/\s*,\s*/,/g; # remove spaces around commas
+
+# figure out what we're doing and the input and output files...
+if ( ! $Input_file ) {
+ if ($#ARGV == 0) {
+ $Input_file = $ARGV[0];
+ } else {
+ $Input_file = '-'; # stdin; hmm...
+ }
+}
+
+($Inputfile_root,$Inputfile_suff) = &root_and_suffix($Input_file);
+
+# are we "processing" and/or "linking" ?
+if ( ! ($Lit2texi || $Lit2latex)) { # that's easy...
+ $Processing = 1;
+ $Linking = 0;
+} else {
+ $Processing = 1 if $Inputfile_suff !~ /^(itxi|itex|texi|tex)$/;
+ $Linking = ($opt_c) ? 0 : 1;
+}
+
+# table of input-suffixes -> output-suffixes (for "processing");
+# cf. tables in &check_language_stuff
+$ISUFF2OSUFF{'lit'} = '';
+$ISUFF2OSUFF{'lhs'} = 'hs';
+$ISUFF2OSUFF{'lit.hs'} = 'hs';
+$ISUFF2OSUFF{'lprl'} = 'prl';
+$ISUFF2OSUFF{'llex'} = 'lex';
+
+# guess the output filenames (for "processing" and "linking")
+if ( $opt_o ) {
+ if ( $Linking ) {
+ $Link_outfile = $opt_o;
+ } else {
+ $Proc_outfile = $opt_o;
+ }
+}
+if ( !defined($Proc_outfile) ) {
+ if ($Linking) { # got to put it _somewhere_
+ $Proc_outfile = "/usr/tmp/lit2stuff-po.$$";
+
+ } elsif ($Lit2pgm) { # try to be clever
+ if (defined($ISUFF2OSUFF{$Inputfile_suff})) {
+ $Proc_outfile = $Inputfile_root;
+ $Proc_outfile .= '.'.$ISUFF2OSUFF{$Inputfile_suff}
+ if $ISUFF2OSUFF{$Inputfile_suff};
+ } else {
+ print STDERR "$Pgm: don't know the file suffix: $Inputfile_suff\n";
+ $Proc_outfile = '-'; # stdout will do
+ }
+
+ } elsif ($Lit2texi) {
+ $Proc_outfile = $Inputfile_root . '.itxi';
+
+ } elsif ($Lit2latex) {
+ $Proc_outfile = $Inputfile_root . '.itex';
+
+ } else {
+ $Proc_outfile = '-'; # stdout
+ }
+}
+# messing with Link_outfile deferred to later...
+
+&check_language_stuff();
+exit $Status if $Status; # don't proceed if errors
+
+print STDERR "Language info: code=$Code_lang, xref=$Lang_xref, ",
+ "typeset=$Lang_typeset, pagebreak=$Lang_pagebreak\n"
+ if $Verbose;
+
+# now we know the program, the options, and the language info, we load
+# the other (non-language-related) pieces of perl code (roll-your-own
+# dynamic linking...)
+# if ( ! $Quick_lit2pgm) {
+# do 'lit-globals.prl' || die "Giant error 'do'ing lit-globals.prl: $@";
+# do 'lit-reader.prl' || die "Giant error 'do'ing lit-reader.prl: $@";
+#}
+#if ($Lit2pgm) {
+# if (! $Quick_lit2pgm) { # i.e., the slow one
+# do 'lit-2pgm.prl' || die "Giant error 'do'ing lit-2pgm.prl: $@";
+# }
+# boot changes
+# # we _always_ need something for line directives
+# do "lit-2pgm-$Code_lang.prl"
+# || die "Giant error 'do'ing lit-2pgm-$Code_lang.prl: $@";
+#
+#} else {
+# die "can't use lit2pgm.BOOT except for lit2pgm'ming"
+#}
+
+# NOW WE START DRIVING...
+
+# first: we handle "quick" lit2pgm
+if ($Quick_lit2pgm) {
+
+ # check that no incompatible lit2pgm options were used
+ die "Can only get ribbon 'main' with lit2pgm -q option\n"
+ if ($Ribbons_to_get ne 'main');
+ die "Can't follow \\input{}s with lit2pgm -q option\n"
+ if ($Follow_inputs);
+
+ $pipe_string = "$Lit_deatify $Verbose 0 $Lit2what $Input_file | expand";
+ print STDERR "QUICK LIT2PGM:in=$pipe_string\n" if $Verbose;
+ print STDERR " out=$Proc_outfile\n" if $Verbose;
+ &do_std_opens($pipe_string,$Proc_outfile);
+
+ # this "quick" loop does as little as possible
+ while (<INPIPE>) {
+ if ( /^srcfile!_!(.*)!_!(.*)!_!/) {
+# boot change:
+# print &mk_line_directive($1,$2);
+;
+ } else {
+ print $_ ;
+ }
+ }
+ &do_std_closes();
+ exit $Status;
+}
+
+# continue with various kinds of "processing" ...
+
+if ($Lit2pgm) {
+ print STDERR "LIT2PGM:out=$Proc_outfile\n" if $Verbose;
+ &spit_out_ribbons_code(split(/,/, $Ribbons_to_get));
+ &do_std_closes();
+ exit $Status;
+}
+
+# line 418 "lit2stuff.lprl"
+sub check_language_stuff {
+
+ # fixed tables of "language"-related info
+
+ $ISUFF2LANG{'lit'} = 'none';
+ $ISUFF2LANG{'lc'} = 'c';
+ $ISUFF2LANG{'lhs'} = 'hs';
+ $ISUFF2LANG{'lit.hs'}='hs';
+ $ISUFF2LANG{'lprl'} = 'prl';
+ $ISUFF2LANG{'llex'} = 'lex';
+
+ $STD_LANGS = 'none,c,hs,prl,lex'; # fully supported (?)
+
+ $XREF_HINTS = ''; # could have more...
+ $PAGEBREAK_HINTS = '';
+ $TYPESET_HINTS = '';
+
+ $Code_lang =
+ ($opt_l) ? $opt_l
+ : (defined($ISUFF2LANG{$Inputfile_suff})) ? $ISUFF2LANG{$Inputfile_suff}
+ : 'none';
+ $Lang_pagebreak = ($opt_p) ? $opt_p : '';
+ $Lang_typeset = ($opt_t) ? $opt_t : '';
+ $Lang_xref = ($opt_x) ? $opt_x : '';
+
+ &not_OK("","","xref hints unknown: $Lang_xref\n")
+ if $Lang_xref && index( $XREF_HINTS, $Lang_xref ) < 0;
+ &not_OK("","","pagebreak hints unknown: $Lang_pagebreak\n")
+ if $Lang_pagebreak && index( $PAGEBREAK_HINTS, $Lang_pagebreak ) < 0;
+ &not_OK("","","typeset hints unknown: $Lang_typeset\n")
+ if $Lang_typeset && index( $TYPESET_HINTS, $Lang_typeset ) < 0;
+}
+# line 472 "lit2stuff.lprl"
+sub do_std_opens { # opens INPIPE, and OUTF; selects the latter
+
+ local($pipe_string,$output_file) = @_;
+
+ # check it output is to a pipe
+ $output_file = ">$output_file" if $output_file !~ /^\|/;
+
+ open(INPIPE, "$pipe_string |")
+ || die "$Pgm: can't start prefilter pipe: $pipe_string\n";
+ open(OUTF, "$output_file")
+ || die "$Pgm: can't open output file: $output_file\n";
+ select(OUTF);
+}
+
+sub do_std_closes { # closes INPIPE and OUTF; re-selects STDOUT
+
+ close(INPIPE);
+ # most regrettably, this only tells if the _last_ thing
+ # in the pipeline croaked...
+ if ($? >> 8) {
+ print STDERR "$Pgm: error(s) from prefilter pipe\n";
+ unlink("/usr/tmp/lit2stuff-po.$$"); # this might exist...
+ exit 1;
+ }
+ close(OUTF);
+ if ($? >> 8) {
+ print STDERR "$Pgm: error in closing output file: $?\n";
+ unlink("/usr/tmp/lit2stuff-po.$$"); # this might exist...
+ exit 1;
+ }
+ select(STDOUT);
+}
+
+sub not_OK { # report error, increment $Status, but keep going
+ local($srcfilename, $srclineno, $msg) = @_;
+ if ($srcfilename) { # not always there
+ print STDERR "$srcfilename:$srclineno: $msg";
+ } else {
+ print STDERR "$Pgm: $msg";
+ }
+ $Status++;
+}
+
+sub filter_string {
+ local($filter, $string) = @_;
+
+ open(FILT, "| $filter > /tmp/lit$$") || die "Can't open in filter_string\n";
+ print FILT $string;
+ close(FILT);
+ if ($? >> 8) { # something went wrong in the pipe ???
+ print STDERR "$Pgm: error(s) in/from filter: $filter\n";
+ }
+ local($filtered_string) = `cat /tmp/lit$$`;
+ unlink("/tmp/lit$$");
+ $filtered_string;
+}
+
+sub deatified2verb_nl { # lit-deatify put 'em in; now we take 'em out
+ local($_) = @_;
+
+ s/\001newline\003/\n/g; # _WITH_ newlines
+ s/\001lbrace\003/\{/g;
+ s/\001rbrace\003/\}/g;
+ s/\001rbracket\003/\]/g;
+
+ $_;
+}
+
+sub deatified2verb { # without newlines
+ local($_) = @_;
+
+ $_ = &deatified2verb_nl($_);
+
+ s/\n/ /g; # the difference; to SPACES
+ $_;
+}
+
+sub de_newlined {
+ local($_) = @_;
+
+ s/\n/\001newline\003/g;
+ $_;
+}
+
+sub root_and_suffix {
+ local($filename) = @_;
+ local($root,$suffix);
+
+ # find the file's "suffix" (NB: *.lit.hs has a 6-letter suffix)
+ if ($filename =~ /\.(lit\.[^\.\/]+)$/) { # cf \input handling in reader
+ $suffix = $1;
+ ($root = $filename) =~ s/\.(lit\.[^\.\/]+)$//;
+
+ } elsif ($filename =~ /\.([^\.\/]+)$/) {
+ $suffix = $1;
+ ($root = $filename) =~ s/\.([^\.\/]+)$//;
+
+ } else {
+ # should there be a warning or something here?
+ $root = '???';
+ $suffix = '???';
+ }
+ ($root, $suffix);
+}
+
diff --git a/web/glasgow/lit2x-0.16/literate/lit2stuff.lprl b/web/glasgow/lit2x-0.16/literate/lit2stuff.lprl
new file mode 100644
index 0000000000..cacb4422fe
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/lit2stuff.lprl
@@ -0,0 +1,775 @@
+% *** MSUB does some substitutions here ***
+% *** grep for $( ***
+%
+\begin{onlystandalone}
+\documentstyle[11pt,literate]{article}
+\begin{document}
+\title{Source for the Glasgow literate programming system}
+\author{(A sheepish) Will Partain}
+\maketitle
+\begin{rawlatex}
+\tableofcontents
+\end{rawlatex}
+\end{onlystandalone}
+
+\section[Source_Introduction]{Source: introduction and overall structure}
+
+This \tr{perl} script is a driver that converts literate scripts into other
+useful forms. Because the various tasks
+\tr{lit2pgm},\index{lit2pgm} \tr{lit2latex},\index{lit2latex}
+etc., are so similar, there's just one script (which I call
+\tr{lit2stuff}),\index{lit2stuff} with some parts conditionally
+included/executed, depending on how
+the script was invoked (exactly one of the variables @$Lit2pgm@,
+@$Lit2latex@, and @$Lit2texi@ will be @1@, the others @0@).
+
+\tr{lit2stuff} is written in \tr{perl}, so some tasks are not as
+conveniently expressed as one might wish. For example, \tr{perl} is
+line-oriented so, for example, chasing down the contents of a multi-line
+\tr{\title{...}} is, in the general case, unpleasant.
+\tr{lit2stuff} uses helper programs to cope with such things. You'll
+see 'em along the way.
+
+\section[Naming_and_background]{Naming conventions, perl hackery, etc.}
+
+[How I use names, and so on.]
+
+\section[Global_data_structures]{Global data structures}
+\downsection
+\input{lit-globals.lprl}
+\input{lit-link-globals.lprl}
+\upsection
+
+\section[Lit_initialization]{Initialization and command-line argument checking}
+
+First, the program must have been invoked with an approved name:
+\begin{code}
+($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/;
+$LIT_VERSION = '0.16';
+
+# an initial -A<name> option overrides the name
+if ($#ARGV >= 0 && $ARGV[0] =~ /^-A(lit2)(pgm|texi|latex)$/) {
+ $Pgm = $1.$2;
+ shift(@ARGV);
+}
+$Lit2pgm = ($Pgm eq 'lit2pgm') ? 1 : 0;
+$Lit2latex = ($Pgm eq 'lit2latex') ? 1 : 0;
+$Lit2texi = ($Pgm eq 'lit2texi') ? 1 : 0;
+$Lit2depend = ($Pgm eq 'mkdependlit') ? 1 : 0;
+$Lit2changelog = ($Pgm eq 'lit2changelog') ? 1 : 0;
+$Lit2text = ($Pgm eq 'lit2text') ? 1 : 0;
+die "$Pgm: must be invoked as lit2pgm, lit2texi, lit2latex, mkdependlit, lit2changelog, or lit2text (or use -A<name>)\n"
+ if (!($Lit2pgm || $Lit2latex || $Lit2texi || $Lit2depend || $Lit2changelog || $Lit2text));
+
+# $Lit2what will be set after we know $Quick_lit2pgm
+
+$Status = 0; # just used for exit() status
+\end{code}
+
+Unravel the command-line options with one of the perl-library @getopt@
+routines, then transfer that information to more pleasantly-named
+global variables (see the User Guide
+\standaloneornot{}{[Section~\ref{Literate_guide}]}
+for what passes as good command-line arguments):
+
+\begin{code}
+# really only needed if perl is misinstalled. (and can't find getopts.pl)
+if ( $(INSTALLING) ) {
+ unshift(@INC, '$(INSTDATADIR_LITERATE)');
+} else {
+ unshift(@INC, '$(TOP_PWD)/$(CURRENT_DIR)'); # absolutize the paths
+}
+
+do 'getopts.pl' || die "Giant error 'do'ing getopts.pl: $@";
+
+$Usage = "usage: $Pgm ".
+ '[-i input-file] '.
+ '[-I LITINPUTS-path-additions] '.
+ '[-o output-file] ';
+$Usage .= '[-cdnqv] '.
+ '[-r ribbons] '.
+ "[input-file]\n" if $Lit2pgm;
+$Usage .= '[-cdLnOSv] '.
+ '[-f nodename-suffix] '.
+ '[-N infofilename] '.
+ '[-[lx] language] '.
+ '[-s stop-list-file] '.
+ "[input-file]\n" if $Lit2texi;
+$Usage .= '[-cdDnOSv] '.
+ '[-g node-name] '.
+ '[-[lptx] language] '.
+ '[-s stop-list-file] '.
+ "[input-file]\n" if $Lit2latex;
+$Usage .= '[-dv] '.
+ "[input-file]\n" if $Lit2depend;
+$Usage .= '[-dnv] '.
+ "[input-file]\n" if $Lit2changelog;
+$Usage .= '[-dnv] '.
+ "[input-file]\n" if $Lit2text;
+
+if ( ($Lit2pgm && ! &Getopts('cdH:I:i:no:qr:v'))
+ || ($Lit2texi && ! &Getopts('cdf:H:I:i:Ll:nN:Oo:Ss:vx:'))
+ || ($Lit2latex && ! &Getopts('cdDg:H:I:i:l:no:Op:Ss:t:vx:'))
+ || ($Lit2depend && ! &Getopts('dH:I:i:o:v'))
+ || ($Lit2text && ! &Getopts('dH:I:i:no:v'))
+ || ($Lit2changelog && ! &Getopts('dH:I:i:no:v'))) {
+ print STDERR $Usage;
+ exit 1;
+} elsif ($#ARGV > 0) {
+ print STDERR "$Pgm: cannot have more than one input file: @ARGV \n";
+ print STDERR $Usage;
+ exit 1;
+}
+# SHARED OPTIONS
+$Debugging = ($opt_d) ? 1 : 0;
+$Verbose = ($Debugging | $opt_v) ? 1 : 0;
+print STDERR "Glasgow literate programming system, version $LIT_VERSION\n" if $Verbose;
+$Input_file = ($opt_i) ? $opt_i : '';
+# -o <output file> handled after deciding if linking
+
+$Litinputs = '.';
+$Litinputs_adds = ($opt_I) ? $opt_I : '';
+$Litinputs = "$Litinputs_adds:$Litinputs" if $Litinputs && $Litinputs_adds;
+
+# where all the assisting code is found (HARDWIRED)
+if ($opt_H) {
+ # no error checking; you get what you deserve
+ ($LIB_ARCH_DIR,$LIB_DIR) = split(/:/,$opt_H);
+} elsif ( $(INSTALLING) ) {
+ $LIB_ARCH_DIR = '$(INSTLIBDIR_LITERATE)';
+ $LIB_DIR = '$(INSTDATADIR_LITERATE)';
+} else {
+ $LIB_ARCH_DIR = '$(TOP_PWD)/$(CURRENT_DIR)'; # absolutize the paths
+ $LIB_DIR = '$(TOP_PWD)/$(CURRENT_DIR)';
+}
+unshift(@INC, $LIB_DIR); # adding to; for .prl libraries sucked in at runtime
+#
+# now the (derived) names of all the helpers
+$Lit_inputter = "$LIB_ARCH_DIR/lit-inputter";
+$Lit_deatify = "$LIB_ARCH_DIR/lit-deatify";
+$Lit_verb2latex = "$LIB_ARCH_DIR/lit-verb2latex";
+
+# this should be done a better way...
+$Tgrind_pgm = '$(TGRIND_HELPER)';
+
+# finish knowing myself; must agree with lit-deatify.llex
+$Quick_lit2pgm = ($opt_q) ? 1 : 0;
+$Lit2what = 1 if $Quick_lit2pgm;
+$Lit2what = 2 if $Lit2pgm && ! $Quick_lit2pgm;
+$Lit2what = 3 if $Lit2texi;
+$Lit2what = 4 if $Lit2latex;
+$Lit2what = 5 if $Lit2depend;
+$Lit2what = 6 if $Lit2changelog;
+$Lit2what = 7 if $Lit2text;
+
+# LESS SHARED OPTIONS
+$Codedef_blurbs = ($opt_D) ? 1 : 0;
+$Grab_node = ($opt_g) ? $opt_g : 'Top';
+$Infofilename = ($opt_N) ? $opt_N : ''; # see do_setfilename
+$Follow_inputs = ($opt_n) ? 1 : 0;
+$Show_node_owner= ($opt_O) ? 1 : 0;
+$Nodename_suffix= ($opt_f) ? $opt_f : '';
+$Opt_node_links = ($opt_L) ? 1 : 0;
+$Standalone_doc = ($opt_S) ? 1 : 0;
+
+$Stoplist_file = ($opt_s) ? $opt_s : '';
+# for now, stop lists are simply words to be ignored
+if ($Stoplist_file) {
+ if ( ! -f $Stoplist_file) {
+ &not_OK('','',"stop-list file does not exist: $Stoplist_file\n");
+ } else {
+ open(STOPF,"<$Stoplist_file") || die "Can't open file: $Stoplist_file\n";
+ while (<STOPF>) {
+ chop;
+ $IGNORE_WD{$_} = 1; # no questions asked...
+ }
+ close(STOPF);
+ }
+}
+
+$Ribbons_to_get = ($opt_r) ? $opt_r : 'main';
+$Ribbons_to_get =~ s/\s*,\s*/,/g; # remove spaces around commas
+
+# figure out what we're doing and the input and output files...
+if ( ! $Input_file ) {
+ if ($#ARGV == 0) {
+ $Input_file = $ARGV[0];
+ } else {
+ $Input_file = '-'; # stdin; hmm...
+ }
+}
+
+($Inputfile_root,$Inputfile_suff) = &root_and_suffix($Input_file);
+@Files_to_tidy = ();
+
+# are we "processing" and/or "linking" ?
+if ( ! ($Lit2texi || $Lit2latex)) { # that's easy...
+ $Processing = 1;
+ $Linking = 0;
+} else {
+ $Processing = 1 if $Inputfile_suff !~ /^(itxi|itex|texi|tex)$/;
+ $Linking = ($opt_c) ? 0 : 1;
+}
+
+# table of input-suffixes -> output-suffixes (for "processing");
+# cf. tables in &check_language_stuff
+$ISUFF2OSUFF{'lit'} = '';
+$ISUFF2OSUFF{'lhs'} = 'hs';
+$ISUFF2OSUFF{'lit.hs'} = 'hs';
+$ISUFF2OSUFF{'lprl'} = 'prl';
+$ISUFF2OSUFF{'llex'} = 'lex';
+$ISUFF2OSUFF{'lhc'} = 'hc';
+$ISUFF2OSUFF{'lc'} = 'c';
+$ISUFF2OSUFF{'lh'} = 'h';
+$ISUFF2OSUFF{'ltex'} = 'tex';
+$ISUFF2OSUFF{'lit.tex'} = 'tex';
+$ISUFF2OSUFF{'ljm'} = 'jm'; # mkworld-ery
+$ISUFF2OSUFF{'lf'} = 'f'; # Literate Fortran (adriaan@dcs.qmw.ac.uk)
+
+# guess the output filenames (for "processing" and "linking")
+if ( $opt_o ) {
+ @Files_to_tidy = ( $opt_o );
+ if ( $Linking ) {
+ $Link_outfile = $opt_o;
+ } else {
+ $Proc_outfile = $opt_o;
+ }
+}
+if ( !defined($Proc_outfile) ) {
+ if ($Linking) { # got to put it _somewhere_
+ $Proc_outfile = "$(TMPDIR)/lit2stuff-po.$$";
+
+ } elsif ($Lit2pgm) { # try to be clever
+ if (defined($ISUFF2OSUFF{$Inputfile_suff})) {
+ $Proc_outfile = $Inputfile_root;
+ $Proc_outfile .= '.'.$ISUFF2OSUFF{$Inputfile_suff}
+ if $ISUFF2OSUFF{$Inputfile_suff};
+ } else {
+ print STDERR "$Pgm: don't know the file suffix: $Inputfile_suff\n";
+ $Proc_outfile = '-'; # stdout will do
+ }
+
+ } elsif ($Lit2texi) {
+ $Proc_outfile = $Inputfile_root . '.itxi';
+
+ } elsif ($Lit2latex) {
+ $Proc_outfile = $Inputfile_root . '.itex';
+
+ } else {
+ $Proc_outfile = '-'; # stdout
+ }
+ @Files_to_tidy = ( $Proc_outfile ) if $Proc_outfile ne '-';
+}
+# messing with Link_outfile deferred to later...
+
+&check_language_stuff();
+exit $Status if $Status; # don't proceed if errors
+
+# here we go: set up signal handler
+sub quit_upon_signal {
+ # delete any files to tidy
+ print STDERR "deleting... @Files_to_tidy\n" if $Verbose && $#Files_to_tidy >= 0;
+ unlink @Files_to_tidy if $#Files_to_tidy >= 0;
+ exit 1;
+}
+$SIG{'INT'} = 'quit_upon_signal';
+$SIG{'QUIT'} = 'quit_upon_signal';
+
+print STDERR "Language info: code=$Code_lang, xref=$Lang_xref, ",
+ "typeset=$Lang_typeset, pagebreak=$Lang_pagebreak\n"
+ if $Verbose;
+
+# now we know the program, the options, and the language info, we load
+# the other (non-language-related) pieces of perl code (roll-your-own
+# dynamic linking...)
+if ( ! $Quick_lit2pgm) {
+ do 'lit-globals.prl' || die "Giant error 'do'ing lit-globals.prl: $@";
+ do 'lit-reader.prl' || die "Giant error 'do'ing lit-reader.prl: $@";
+}
+if ($Lit2pgm) {
+ if (! $Quick_lit2pgm) { # i.e., the slow one
+ do 'lit-2pgm.prl' || die "Giant error 'do'ing lit-2pgm.prl: $@";
+ }
+ # we _always_ need something for line directives
+ do "lit-2pgm-$Code_lang.prl"
+ || die "Giant error 'do'ing lit-2pgm-$Code_lang.prl: $@";
+
+} elsif ($Lit2depend) {
+ do 'lit-2depend.prl' || die "Giant error 'do'ing lit-2depend.prl: $@";
+
+} elsif ($Lit2changelog) {
+ do 'lit-2changes.prl' || die "Giant error 'do'ing lit-2changes.prl: $@";
+
+} elsif ($Lit2text) {
+ do 'lit-2text.prl' || die "Giant error 'do'ing lit-2text.prl: $@";
+
+} else {
+ # creating a document...
+ do 'lit-2doc.prl' || die "Giant error 'do'ing lit-2doc.prl: $@";
+ # language-specific stuff (most of it)
+ do "lit-2doc-$Code_lang.prl"
+ || die "Giant error 'do'ing lit-2doc-$Code_lang.prl: $@";
+ if ( $Lit2texi ) {
+ do 'lit-2texi.prl' || die "Giant error 'do'ing lit-2texi.prl: $@";
+ if ($Processing) {
+ do "lit-2texi-$Code_lang.prl"
+ || die "Giant error 'do'ing lit-2texi-$Code_lang.prl: $@";
+ # non-Code_lang xref/typeset/pagebreak code would be slurped here
+ # [not implemented]
+ }
+ }
+ if ( $Lit2latex ) {
+ do 'lit-2latex.prl' || die "Giant error 'do'ing lit-2latex.prl: $@";
+ if ($Processing) {
+ do "lit-2latex-$Code_lang.prl"
+ || die "Giant error 'do'ing lit-2latex-$Code_lang.prl: $@";
+ # non-Code_lang xref/typeset/pagebreak code would be slurped here
+ # [not implemented]
+ }
+ }
+ if ( $Linking ) {
+ do 'lit-link-globals.prl' || die "Giant error 'do'ing lit-link-globals.prl: $@";
+ do 'lit-linker.prl' || die "Giant error 'do'ing lit-linker.prl: $@";
+ }
+}
+
+# NOW WE START DRIVING...
+
+# first: we handle "quick" lit2pgm
+if ($Quick_lit2pgm) {
+
+ # check that no incompatible lit2pgm options were used
+ die "Can only get ribbon 'main' with lit2pgm -q option\n"
+ if ($Ribbons_to_get ne 'main');
+ die "Can't follow \\input{}s with lit2pgm -q option\n"
+ if ($Follow_inputs);
+
+ $Input_file = '' if $Input_file eq '-';
+ $pipe_string = "(echo \"srcfile!_!$Input_file!_!1!_!\" ; expand $Input_file) | " .
+ "$Lit_deatify $Verbose 0 $Lit2what -";
+ print STDERR "QUICK LIT2PGM:in=$pipe_string\n" if $Verbose;
+ print STDERR " out=$Proc_outfile\n" if $Verbose;
+ &do_std_opens($pipe_string,$Proc_outfile);
+
+ # this "quick" loop does as little as possible
+ while (<INPIPE>) {
+ if ( /^srcfile!_!(.*)!_!(.*)!_!/) {
+ print &mk_line_directive($1,$2);
+ } else {
+ print $_ ;
+ }
+ }
+ &do_std_closes();
+ exit $Status;
+}
+
+# second: we handle lit2depend
+if ($Lit2depend) {
+ $Follow_inputs = 1; # that's the whole point
+ # just using lit-inputter to follow \input's
+
+ $pipe_string = "$Lit_inputter $Verbose $Follow_inputs $Litinputs $Input_file";
+ print STDERR "MKDEPENDLIT:in=$pipe_string\n" if $Verbose;
+ print STDERR " out=$Proc_outfile\n" if $Verbose;
+ &do_std_opens($pipe_string,$Proc_outfile);
+
+ # lineno 1 means we just started the file
+ # look for these and deduce dependency info (a hack)
+ @Depend_lines = ();
+ while (<INPIPE>) {
+ if ( /^srcfile!_!(.*)!_!1!_!/) {
+ &collect_dependencies($1);
+ }
+ }
+ &do_std_closes();
+ &mangle_Makefile();
+ exit $Status;
+}
+
+# all other invocations of "processing" (slow lit2pgm, lit2latex,
+# lit2texi, lit2changelog) need the input "parsed" and stuffed into
+# the global data structures, so we do that now.
+
+if ($Processing) {
+ # (would really like to get \input'ing over to deatify...)
+
+ $pipe_string = "$Lit_inputter $Verbose $Follow_inputs $Litinputs $Input_file | ".
+ "expand | ".
+ "$Lit_deatify $Verbose 0 $Lit2what -";
+ # lit-deatify last so we get its error report
+ print STDERR "PARSING:in=$pipe_string\n" if $Verbose;
+ print STDERR " out=$Proc_outfile\n" if $Verbose;
+
+ &do_std_opens($pipe_string,$Proc_outfile);
+
+ &read_and_categorize_input(); # reads <INPIPE>
+ &fiddle_line_numbers() if ! $Lit2pgm;
+
+ if ($Lit2texi || $Lit2latex) { # want this before dumping...
+ &find_interesting_codethings();
+ }
+
+ if ($Debugging) {
+ print STDERR "AFTER \"PARSING\" :-\n";
+ &dump_sections_and_blocks();
+ }
+}
+
+# continue with various kinds of "processing" ...
+
+if ($Lit2pgm) {
+ print STDERR "LIT2PGM:out=$Proc_outfile\n" if $Verbose;
+ &spit_out_ribbons_code(split(/,/, $Ribbons_to_get));
+ &do_std_closes();
+ exit $Status;
+}
+
+if ($Lit2changelog) {
+ print STDERR "LIT2CHANGELOG:out=$Proc_outfile\n" if $Verbose;
+ &spit_out_change_info();
+ &do_std_closes();
+ exit $Status;
+}
+
+if ($Lit2text) {
+ print STDERR "LIT2TEXT:out=$Proc_outfile\n" if $Verbose;
+ &spit_out_raw_text();
+ &do_std_closes();
+ exit $Status;
+}
+
+if ($Processing) {
+ # now either lit2latex or lit2texi...
+ print STDERR "LIT2DOC:out=$Proc_outfile\n" if $Verbose;
+
+ &do_text_substitutions(); # \defines
+
+ &print_intermed_document();
+
+ &do_std_closes();
+}
+
+## (I'd rather keep going... )
+## close up and unlink temp outfile file if we are about to die
+#unlink("$(TMPDIR)/lit2stuff-po.$$") if $Status;
+#exit $Status if $Status || ! $Linking;
+exit $Status if ! $Linking;
+
+# NOW WE'RE TO "linking" ... (lit2texi and lit2latex only)
+
+# make sure we know where to put the output (_before_ redefining Input_file)
+if ( !defined($Link_outfile) ) {
+ $Link_outfile = $Inputfile_root . '.texi' if $Lit2texi;
+ $Link_outfile = $Inputfile_root . '.tex' if $Lit2latex;
+ @Files_to_tidy = ( $Link_outfile );
+}
+# readjust notions of "input" file if just processed
+if ( $Processing ) {
+ $Input_file = $Proc_outfile;
+}
+
+# $Input_file is the root of a bunch of i{tex,texi} files to be glued
+# together; the sectioning needs to be fixed and unresolved node refs
+# need to be fixed.
+# each file has a table of relevant info at the beginning
+# 1st pass: go \inputting down through them, reading those tables
+# 2nd pass: go \inputting down through them, fixing things and writing
+
+&first_link_pass(); # GO!!!
+
+if ($Debugging) {
+ print STDERR "AFTER LINKER FIRST PASS :-\n";
+ &dump_sections_and_blocks();
+}
+
+# # (I'd rather keep going)
+# # unlink temp outfile file if we are about to die
+# unlink("$(TMPDIR)/lit2stuff-po.$$") if $Status;
+# exit $Status if $Status;
+
+&second_link_pass();
+
+# unlink temp outfile no matter what
+unlink("$(TMPDIR)/lit2stuff-po.$$");
+exit $Status;
+\end{code}
+
+\begin{code}
+sub check_language_stuff {
+
+ # fixed tables of "language"-related info
+
+ $ISUFF2LANG{'lit'} = 'none';
+ $ISUFF2LANG{'lhc'} = 'c';
+ $ISUFF2LANG{'lc'} = 'c';
+ $ISUFF2LANG{'lh'} = 'c';
+ $ISUFF2LANG{'lhs'} = 'hs';
+ $ISUFF2LANG{'lit.hs'}='hs';
+ $ISUFF2LANG{'lprl'} = 'prl';
+ $ISUFF2LANG{'llex'} = 'lex';
+ $ISUFF2LANG{'ljm'} = 'jm'; # mkworld-ery
+ $ISUFF2LANG{'lf'} = 'f'; # Literate Fortran (adriaan@dcs.qmw.ac.uk)
+
+ $STD_LANGS = 'none,c,hs,prl,lex,jm,f'; # fully supported (?)
+
+ $XREF_HINTS = 'noindex'; # could have more...
+ $PAGEBREAK_HINTS = '';
+ $TYPESET_HINTS = 'tgrind,ruled,unruled,bird,nobird';
+
+ $Code_lang =
+ ($opt_l) ? $opt_l
+ : (defined($ISUFF2LANG{$Inputfile_suff})) ? $ISUFF2LANG{$Inputfile_suff}
+ : 'none';
+ $Lang_pagebreak = ($opt_p) ? $opt_p : '';
+ $Lang_typeset = ($opt_t) ? $opt_t : '';
+ $Lang_xref = ($opt_x) ? $opt_x : '';
+
+ &not_OK("","","xref hint(s) unknown: $Lang_xref\n")
+ if $Lang_xref && &hints_not_OK( $XREF_HINTS, $Lang_xref );
+ &not_OK("","","pagebreak hint(s) unknown: $Lang_pagebreak\n")
+ if $Lang_pagebreak && &hints_not_OK( $PAGEBREAK_HINTS, $Lang_pagebreak );
+ &not_OK("","","typeset hint(s) unknown: $Lang_typeset\n")
+ if $Lang_typeset && &hints_not_OK( $TYPESET_HINTS, $Lang_typeset );
+}
+\end{code}
+
+\section[Misc_routines]{Miscellaneous subroutines}
+
+\begin{code}
+sub do_std_opens { # opens INPIPE, and OUTF; selects the latter
+
+ local($pipe_string,$output_file) = @_;
+
+ # check it output is to a pipe
+ $output_file = ">$output_file" if $output_file !~ /^\|/;
+
+ open(INPIPE, "$pipe_string |")
+ || die "$Pgm: can't start prefilter pipe: $pipe_string\n";
+ open(OUTF, "$output_file")
+ || die "$Pgm: can't open output file: $output_file\n";
+ select(OUTF);
+}
+
+sub do_std_closes { # closes INPIPE and OUTF; re-selects STDOUT
+
+ close(INPIPE);
+ # most regrettably, this only tells if the _last_ thing
+ # in the pipeline croaked...
+ if ($? >> 8) {
+ print STDERR "$Pgm: error(s) from prefilter pipe\n";
+ unlink("$(TMPDIR)/lit2stuff-po.$$"); # this might exist...
+ if ($#Files_to_tidy >= 0) {
+ print STDERR "rm -f @Files_to_tidy\n" if $Verbose;
+ unlink ( @Files_to_tidy );
+ }
+ exit 1;
+ }
+ close(OUTF);
+ if ($? >> 8) {
+ print STDERR "$Pgm: error in closing output file: $?\n";
+ unlink("$(TMPDIR)/lit2stuff-po.$$"); # this might exist...
+ exit 1;
+ }
+ select(STDOUT);
+}
+
+sub not_OK { # report error, increment $Status, but keep going
+ local($srcfilename, $srclineno, $msg) = @_;
+ if ($srcfilename) { # not always there
+ print STDERR "$srcfilename:$srclineno: $msg";
+ } else {
+ print STDERR "$Pgm: $msg";
+ }
+ $Status++;
+}
+
+sub hints_not_OK { # return 1 or '' depending on if all hints are in valid list or not
+ local($valid_hints,$given_hints) = @_;
+ local($h);
+
+ foreach $h (split(/,/,$given_hints)) {
+ return(1) if index($valid_hints,$h) < 0;
+ }
+ '';
+}
+
+sub filter_string {
+ local($filter, $string) = @_;
+
+ open(FILT, "| $filter > /tmp/lit$$") || die "Can't open in filter_string\n";
+ print FILT $string;
+ close(FILT);
+ if ($? >> 8) { # something went wrong in the pipe ???
+ print STDERR "$Pgm: error(s) in/from filter: $filter\n";
+ }
+# local($filtered_string) = `cat /tmp/lit$$`; # perl bug
+ $filtered_string = `cat /tmp/lit$$`;
+ unlink("/tmp/lit$$");
+ $filtered_string;
+}
+
+sub deatified2verb_nl { # lit-deatify put 'em in; now we take 'em out
+ local($_) = @_;
+
+ s/\001newline\003/\n/g; # _WITH_ newlines
+ s/\001lbrace\003/\{/g;
+ s/\001rbrace\003/\}/g;
+ s/\001rbracket\003/\]/g;
+
+ $_;
+}
+
+sub deatified2verb { # without newlines
+ local($_) = @_;
+
+ $_ = &deatified2verb_nl($_);
+
+ s/\n/ /g; # the difference; to SPACES
+ $_;
+}
+
+sub de_newlined {
+ local($_) = @_;
+
+ s/\n/\001newline\003/g;
+ $_;
+}
+
+sub root_and_suffix {
+ local($filename) = @_;
+ local($root,$suffix);
+
+ # find the file's "suffix" (NB: *.lit.hs has a 6-letter suffix)
+ if ($filename =~ /\.(lit\.[^\.\/]+)$/) { # cf \input handling in reader
+ $suffix = $1;
+ ($root = $filename) =~ s/\.(lit\.[^\.\/]+)$//;
+
+ } elsif ($filename =~ /\.([^\.\/]+)$/) {
+ $suffix = $1;
+ ($root = $filename) =~ s/\.([^\.\/]+)$//;
+
+ } else {
+ # should there be a warning or something here?
+ $root = '???';
+ $suffix = '???';
+ }
+ ($root, $suffix);
+}
+
+\end{code}
+
+\section[Reader_feeding]{Pre-processing programs that feed the reader}
+\downsection
+% the inputter that we hope will go away
+\input{lit-inputter.lprl}
+
+% the pre-processing filter, a lex script
+\input{lit-deatify.llex}
+\upsection
+
+\section[Reader]{The input reader and categorizer}
+\downsection
+\input{lit-reader.lprl}
+\upsection
+
+\section[Language_independent_processing]{Language-independent processing code}
+
+``Language''-specific code is described after the linker.
+
+\downsection
+\input{lit-2pgm.lprl}
+% for both lit2texi and lit2latex
+\input{lit-2doc.lprl}
+\input{lit-2texi.lprl}
+\input{lit-2latex.lprl}
+\input{lit-2depend.lprl}
+\input{lit-2changes.lprl}
+\upsection
+
+\section[Linking_code]{Language-independent code for linking}
+\downsection
+\input{lit-linker.lprl}
+\upsection
+
+\section[Language_specific_processing]{Code-language-specific processing}
+
+This code only applies for \tr{lit2texi} and \tr{lit2latex}.
+
+\downsection
+\section[Language_none]{Special stuff for language \tr{none}}
+\downsection
+\input{lit-2pgm-none.lprl}
+\input{lit-2doc-none.lprl}
+\input{lit-2texi-none.lprl}
+\input{lit-2latex-none.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_hs]{Special stuff for language \tr{hs} (Haskell)}
+\downsection
+\input{lit-2pgm-hs.lprl}
+\input{lit-2doc-hs.lprl}
+\input{lit-2texi-hs.lprl}
+\input{lit-2latex-hs.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_prl]{Special stuff for language \tr{prl} (Perl)}
+\downsection
+\input{lit-2pgm-prl.lprl}
+\input{lit-2doc-prl.lprl}
+\input{lit-2texi-prl.lprl}
+\input{lit-2latex-prl.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_C]{Special stuff for language \tr{c} (C)}
+\downsection
+\input{lit-2pgm-c.lprl}
+\input{lit-2doc-c.lprl}
+\input{lit-2texi-c.lprl}
+\input{lit-2latex-c.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_lex]{Special stuff for language \tr{lex}}
+\downsection
+\input{lit-2pgm-lex.lprl}
+\input{lit-2doc-lex.lprl}
+\input{lit-2texi-lex.lprl}
+\input{lit-2latex-lex.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_Fortran]{Special stuff for language \tr{f}}
+\downsection
+\input{lit-2pgm-f.lprl}
+\input{lit-2doc-f.lprl}
+\input{lit-2texi-f.lprl}
+\input{lit-2latex-f.lprl}
+\upsection
+\upsection
+
+\downsection
+\section[Language_jm]{Special stuff for language \tr{jm} (``make world'' stuff)}
+
+This type of input file is a mixture of C-pre-processor stuff and
+\tr{make} stuff.
+
+\downsection
+\input{lit-2pgm-jm.lprl}
+\input{lit-2doc-jm.lprl}
+\input{lit-2texi-jm.lprl}
+\input{lit-2latex-jm.lprl}
+\upsection
+\upsection
+
+\begin{onlystandalone}
+\printindex
+\end{document}
+\end{onlystandalone}
diff --git a/web/glasgow/lit2x-0.16/literate/typesetting-code b/web/glasgow/lit2x-0.16/literate/typesetting-code
new file mode 100644
index 0000000000..7553426a07
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/literate/typesetting-code
@@ -0,0 +1,1061 @@
+From piet@cs.ruu.nl Thu Oct 10 20:05:48 1991
+From: piet@cs.ruu.nl (Piet van Oostrum)
+Newsgroups: comp.text.tex
+Subject: Typesetting programs with (La)TeX (update)
+Date: 9 Oct 91 14:38:42 GMT
+Reply-To: piet@cs.ruu.nl (Piet van Oostrum)
+Organization: Dept of Computer Science, Utrecht University, The Netherlands
+
+Typesetting program texts with TeX and LaTeX.
+
+This is a survey of methods to typeset program texts with TeX
+and/or LaTeX, usually mixed with other text. The description consists
+mostly of (edited) parts of the documentation of the packages, or messages
+from their authors. I post this to get responses from people that know
+other packages, or updated versions of these. Also I would like to receive
+input about the availability (e.g. by FTP or mail server) of these
+packages, other than the ones mentioned here.
+
+PLEASE MAIL remarks to me, do not post them on the net. After two or three
+weeks I will post an updated version. I might also submit it for
+publication in TUGboat, but then I will have to TeXify it first.
+
+----------------------------------------------------------------------
+Note:
+Several of the packages described below can be obtained from our
+archive, either by ftp-ing from archive.cs.ruu.nl [131.211.80.5], in
+directory TEX/TOOLS, or by sending a message to mail-server@cs.ruu.nl
+containing the line:
+send TEX/TOOLS/INDEX
+or replacing INDEX with an appropriate file name.
+If you are not familiar with the mail-server, use "send HELP" first.
+----------------------------------------------------------------------
+
+Contents:
+
+1. Web and derivatives
+1.1 Cweb
+1.2 Fweb
+1.3 Spiderweb
+2. Tgrind
+3. C2latex
+4. C++2latex
+5. Cprog macros
+6. program environment
+7. Scheme
+8. Ada
+9. Modula-2/Pascal
+10. sundry
+
+------------------------------------------------------------------------
+1.1 Cweb
+------------------------------------------------------------------------
+
+ctangle, cweave - translate CWEB to C and/or TeX
+
+The ctangle program converts a CWEB source document into a C
+program that may be compiled in the usual way. The output
+file includes #line specifications so that debugging can be
+done in terms of the CWEB source file.
+
+The cweave program converts the same CWEB file into a TeX
+file that may be formatted and printed in the usual way. It
+takes appropriate care of typographic details like page
+layout and the use of indentation, italics, boldface,
+etc.,and it supplies extensive cross-index information that
+it gathers automatically.
+
+CWEB allows you to prepare a single document containing all
+the information that is needed both to produce a compilable
+C program and to produce a well-formatted document
+describing the program in as much detail as the writer may
+desire. The user of CWEB ought to be familiar with TeX as
+well as C.
+
+Don Knuth wrote WEB for TeX and Pascal. Silvio Levy designed
+and developed CWEB by adapting the WEB conventions to C and
+by recoding everything in CWEB.
+
+Subject: Levy's Cweb system ported to MS-DOS and VAX/VMS
+
+On the UK TeX Archive at Aston University, directory [tex-archive.web.cweb]
+contains the sources for building Silvio Levy's CWEB system (a WEB suite
+which uses C as the programming language, and TeX as the typesetting
+language) under Unix; this includes a bootstrapping version of Ctangle
+which permits one to get Cweave, etc., working.
+
+Originally this was accompanied by a file VMS.CH which purported to
+port Cweb onto VAX/VMS: however, Vax-C has been revised since Levy
+released this, and further changes were necessary to get the system
+working under VMS. The original VMS.CH has threfore been deleted, and a
+new subdirectory [tex-archive.web.cweb.vms] added to hold the files for
+bootstrapping CWEB onto VMS, and the change files to make this Ctangle
+and Cweave.
+
+In addition, I have ported CWEB to MS-DOS (under Borland's Turbo-C V1.5).
+This was a *major* undertaking, because of clashes between identifiers
+used in ANSI-standard function prototypes in Borland's libraries and
+constants defined in the .web files. Other very extensive changes were
+required to handle the large data structures, which exceed the 64kB
+segment limit of the PC architecture. However, it's all working
+eventually, and the files required for bootstrapping it, and the change
+files, will be found in [tex-archive.web.cweb.ms-dos].
+
+For both of the above ports, the majority of the files of the Unix
+distribution will also be required.
+
+To get started, fetch the file [tex-archive.web.cweb]00readme.txt from
+Aston, either by NIFTP (username PUBLIC, password PUBLIC), or by sending
+mail to <TeXserver@Uk.Ac.Aston.TeX>, with the body of the message
+consisting of the two lines:
+ FILES
+ [tex-archive.web.cweb]00readme.txt
+
+This file will tell you which other files will be required to be fetched
+to have a working version of CWEB under Unix, VMS or MS-DOS.
+
+ Brian {Hamilton Kelly}
+
+------------------------------------------------------------------------
+1.2 Fweb
+------------------------------------------------------------------------
+
+ The WEB System of Structured
+ Software Design and Documentation
+ for C, C++, Fortran, Ratfor, and TeX
+
+ Release 1.22
+ September 21, 1991
+
+ John A. Krommes
+ Princeton University
+
+
+INTRODUCTION
+
+ This message is for new users of the so-called FWEB processors, which
+implement a version of Knuth's WEB system that supports multiple languages and
+a variety of other useful features. If you are already on the FWEB mailing
+list, you should have already received announcements about version 1.22,
+and there is nothing new in the following. If you would like to be added
+to the mailing list, please let me know. (Please supply an Internet
+address if possible.)
+
+ The WEB system consists of EASY-TO-USE software tools that aid in
+software design and documentation. In fact, one can say that the
+documentation IS the code, and vice versa. The documentation facility is
+fully integrated with TeX; book-quality documentation of both text and code
+can be produced essentially automatically. Knuth's fundamental philosophy
+of rearrangable and pluggable modules of code fragments substantially
+simplifies the translation of logical ideas into compilable code. A fully
+indexed, 150 page user manual based on Knuth's original brief memo is
+included with this release.
+
+ The most significant features that distinguish FWEB from its predecessors
+are:
+
+ * SUPPORT for MULTIPLE LANGUAGES
+
+ Presently supported are C, C++, Fortran--77, Fortran--90,
+ Ratfor (RATional FORtran), and (to a limited extent) TeX
+ itself.
+
+ * A POWERFUL, C-LIKE MACRO PREPROCESSOR
+
+ This is particularly useful for Fortran and Ratfor; it
+ makes programming in those languages substantially less
+ painful.
+
+ * A BUILT-IN RATFOR PROCESSOR
+
+ Ratfor endows Fortran with a C-like syntax and certain
+ useful commands such as `for' and `switch'. If you must
+ program in Fortran, try Ratfor.
+
+In addition, many user-friendly features and options have been added to
+this release.
+
+ FWEB was originally released in 1989. Since then, it has undergone
+substantial development and testing on a variety of machines. It is
+written in ANSI C, so it is very portable. An INCOMPLETE list of machines
+and operating systems on which FWEB runs is
+
+ [ansi] (any system that has a fully ANSI C compiler)
+ Apollo
+ Cray-2
+ DECstation
+ IBM-PC (executable files are supplied in addition to source code)
+ NeXT
+ Silicon Graphics Personal Iris
+ Sun (both gcc and cc compilers)
+ VAX/VMS
+
+FWEB is compiled on all machines in the above list except the Apollo before
+each release.
+
+
+OBTAINING VERSION 1.22
+
+ Version 1.22 of the FWEB system is available via anonymous guest ftp from
+Internet host
+
+ lyman.pppl.gov
+
+in public area
+
+ /pub/fweb/v1.22/
+
+Here is a sample ftp dialog. (The precise commands may differ slightly on
+your system.)
+
+ ftp lyman.pppl.gov
+ Name: anonymous
+ Password: guest
+ ftp> cd pub/fweb/v1.22
+ ftp> ls
+ ftp> get READ_ME.FWEB (brief instructions)
+[If you're a new user, you may initially want to skip the next two lines:]
+ ftp> type image
+ ftp> get TAR.v1.22.Z (the entire release)
+[If you get the TAR file, the next two lines are unnecessary:]
+ ftp> cd manual
+ ftp> get INSTALL_FWEB.tex (detailed installation instructions)
+ ftp> quit
+
+Follow the instructions in READ_ME.FWEB or, in much more detail, in
+INSTALL_FWEB.tex. The TAR file contains the complete release, except that
+the executable files for the IBM-PC are not included in it. You must
+obtain those by separate get commands, e.g.,
+
+ ftp> cd boot/pc
+ ftp> mget *.exe
+
+To unpack the TAR file, say in an empty subdirectory
+
+ uncompress TAR.v1.22
+ tar -xvf TAR.v1.22 *
+
+After you've done this, obtain the user manual
+
+ make -n fwebman
+
+to see what will happen, then say ``make fwebman'' to really do it.
+
+ If you can't use ftp, you may be able to use the intermediary of bitftp,
+available through bitnet. You type a valid ftp session into a file, then
+send that file as a message to bitftp@pucc.bitnet. You will get the files
+you requested---e.g., TAR.v1.22.Z---back in the form of a message or
+messages, possibly uuencoded if the file is large. To obtain help on using
+bitftp, send to the above address a message containing the single word
+``help''.
+
+
+NEW in VERSION 1.22
+
+ Version 1.22 is essentially the non-beta version of v1.20--beta that was
+made available in February 1991; it fixes a wide variety of bugs with that
+earlier version, and adds a few new features. A short list of the changes
+and principal bug fixes can be found at the beginning of the detailed
+installation guide INSTALL_FWEB.tex. Note the following in particular [new
+users will be most interested in point (1) about support for LaTeX]:
+
+(1) This version is intended to run with LaTeX as well as with Plain TeX,
+and it is recommended that you use LaTeX if you can. However, this recent
+enhancement has not been tested thoroughly. If you run across macro
+conflicts or other difficulties with using LaTeX in conjunction with
+fweave, please let me know. Note that fwebmac usurps LaTeX's \output
+routine, so you won't be able to do fancy things with output unless you dig
+into the details of fwebmac. But simple LaTeX environments such as tables
+are supposed to work.
+
+(2) IBM--PC users should note that executable files are provided with this
+release, so you don't need a C compiler to proceed. That's the good news.
+The bad news is that I haven't yet been able to squeeze this version down
+enough so that the processors can do themselves. To get a feeling for the
+size of things, you should begin with small test programs and use the -s
+command-line option to look at the memory allocation statistics.
+
+(3) SYSTEM INSTALLERS SHOULD NOTE THAT THE BOOTSTRAPPING PROCEDURE HAS BEEN
+GREATLY SIMPLIFIED. All source files with the exception of one are now
+common to all machines. The exception is custom.web/custom.h. For
+bootstrapping, if a custom.h for your machine is not provided in the
+relevant boot subdirectory, you should first copy a version of custom.h
+into the web subdirectory, then edit that copy following the instructions
+contained in the file. Then compile and link as usual. A short version of
+the bootstrapping procedure is provided in READ_ME.FWEB; more details are
+given in manual/INSTALL_FWEB.tex.
+
+ I continue to be very interested in what changes you must make to get
+FWEB running on your machine. For example, you might have to do something
+that's not covered in custom.h. Unless you know better, always begin by
+trying the ansi customization (in boot/unix/ansi/custom.h). If your C
+compiler isn't ANSI, complain to the vendor; standards are useful. If your
+compiler crashes, complain to the vendor and notify me.
+
+ This version has benefited from the bug reports and suggestions of a
+large number of patient beta-testers and manual readers of v1.20. I am
+very grateful to all of you.
+
+
+OBTAINING HELP and REPORTING BUGS
+
+ FWEB is an evolving project [supported by just one author, in (allegedly)
+spare time] that benefits greatly from user feedback. An attempt is made
+to answer FWEB-related mail promptly---at least once a week, generally more
+frequently. Please feel ABSOLUTELY FREE to request help, advice, and new
+features, and to report bugs or inconsistencies in the documentation.
+Thanks very much for your help.
+
+--- John Krommes
+ September 21, 1991
+
+ krommes@princeton.edu | John A. Krommes
+ | Plasma Physics Laboratory
+ ``princeton.edu'' is a synonym for | P.O. Box 451
+ lyman.pppl.gov == 192.55.106.129 | Princeton, NJ 08543
+
+ | Phone: (609) 243--2606
+
+------------------------------------------------------------------------
+1.3 Spiderweb
+------------------------------------------------------------------------
+
+% Copyright 1989 by Norman Ramsey, Odyssey Research Associates
+% To be used for research purposes only
+% For more information, see file COPYRIGHT in the parent directory
+
+\documentstyle[11pt]{article}
+\title{A note about a new implementation of {\tt WEB}}
+\author{Norman Ramsey\\Odyssey Research Associates}
+\date{July 4, 1988}
+\setcounter{secnumdepth}{0}
+\begin{document}
+\maketitle
+
+\begin{abstract}
+Literate programming has received recent attention in the {\sl
+Communications of the ACM}~\cite{bentley:lp,cvw:loom}.
+{\tt WEB} is a tool intended for literate programming, but
+until recently it was useful only for writing PASCAL programs.
+The author has developed a new tool, {\tt SPIDER}, which reads a
+description of a programming language and writes a {\tt WEB} system
+that can be used to write programs in that language.
+{\tt SPIDER} has been used in the author's organization to build {\tt
+WEB} systems for Ada, C, AWK, and other languages.
+The author hopes that {\tt SPIDER} will enable people to write
+literate programs in many more languages than they could before.
+\end{abstract}
+
+\section{Introduction}
+Donald Knuth developed the {\tt WEB} system of structured documentation
+as part of the {\TeX} project~\cite{knuth:literate-programming}.
+His implementation of {\tt WEB} combined PASCAL and {\TeX}.
+ The {\tt WEB} idea suggests a way of combining {\em any}
+programming language with {\em any} document formatting language,
+but until recently there was no software support for writing in {\tt
+WEB} anything but PASCAL programs.
+In~1987, Silvio Levy rewrote the {\tt WEB} system in C for C,
+while retaining {\TeX} as the formatting language~\cite{levy:cweb}.
+I have has modified Levy's implementation by removing the parts
+that make C the target programming language, and I have
+ added a third tool, {\tt SPIDER}, which complements {\tt WEAVE}
+and {\tt TANGLE}.
+{\tt SPIDER} reads a description of a programming language, and writes
+source code for a {\tt WEAVE} and {\tt TANGLE} which support that
+language.
+Using {\tt SPIDER}, a C~compiler, and an AWK~interpreter, an experienced
+systems programmer can generate in a few hours a {\tt WEB} system for
+an Algol-like language.
+
+\section{Features of Spidery {\tt WEB}}
+An exhaustive list of Spidery {\tt WEB}'s features would interest only
+{\tt WEB} experts,
+but I do want to mention some features that I hope will encourage
+people to use Spidery {\tt WEB}.
+\begin{itemize}
+\item
+{\tt TANGLE} and {\tt WEAVE} can read from multiple files (this
+feature is present in Levy's {\tt CWEB}), and
+{\tt TANGLE} can write to multiple files.
+Included files will be searched for on a path if not found in the
+current directory.
+These features make Spidery {\tt WEB} more usable on systems that have
+{\tt make}.
+\item
+{\tt TANGLE} can expand macros with multiple parameters.
+\item
+The starred sections in Spidery {\tt WEB} can be organized
+hierarchically (in three levels).
+We have a UNIX tool that can extract different pieces of the hierarchy
+from the output of {\tt WEAVE}, so that it is possible to take
+excerpts from {\tt WEB} documents.
+\item
+{\tt TANGLE} writes {\tt \#line} directives, so you can debug at the
+{\tt WEB} source level if your compiler respects the C~conventions for
+{\tt\#line}.
+\item
+Many features of {\tt WEB} seem to exist only to compensate for
+deficiencies in PASCAL, and most of those were dropped in {\tt CWEB}.
+I have changed much of {\tt CWEB} in order to avoid being bound too
+much by C conventions.
+As a result, there are dozens of minor differences between Spidery
+{\tt WEB} and original {\tt WEB}.
+To give just one example, Spidery {\tt WEB} supports
+octal and hexadecimal constants using {\tt WEB}-style
+notation, not the C~notation used in {\tt CWEB}.
+\end{itemize}
+
+\section{Scope of {\tt SPIDER}}
+{\tt SPIDER} can generate {\tt WEB} systems for a variety
+of languages.
+The author has written {\tt SPIDER} description files for C, AWK, Ada,
+SSL (a language that describes attribute grammars to the
+Cornell Synthesizer Generator),
+the Larch Shared Language (a language for describing equational
+theories),
+and Dijkstra's language of guarded commands.
+Debugging the grammar that {\tt WEAVE} uses to
+prettyprint the language is the most time-consuming part of creating a
+{\tt WEB} system for a new target language,
+and {\tt SPIDER} makes it trivial to change that grammar.
+To make a {\tt SPIDER} description file for an Algol-like language
+that uses infix expression notation, an experienced systems programmer
+should be able to adapt an existing {\tt SPIDER} description file very
+quickly.
+
+{\tt SPIDER}'s major limitations are lexical.
+ All Spidery {\tt WEB}s
+assume that spaces and tabs in the input are not significant, except
+as separators;
+this makes it impossible to construct Spidery {\tt WEB}s for languages
+like Fortran and Miranda, where the position of text on a line is
+significant.
+The lexical structures of identifiers, string literals, and numeric
+literals are fixed.
+
+\section{Conclusions}
+{\tt SPIDER} is a modest piece of engineering; it does not introduce
+new ideas.
+{\tt SPIDER} does make it possible to create a new {\tt WEB} quickly,
+and to tinker with it easily.
+The author's group routinely uses Spidery {\tt WEB} to write programs
+in Ada, C, and~SSL, and has been pleased with the result.
+We have written in {\tt WEB} an application of eighteen thousand
+lines, and
+we are very pleased at how easy it has been to review and maintain
+this code.
+The author hopes that the availability of Spidery {\tt WEB} will
+encourage other groups to try literate programming, and that they,
+too, will be pleased with the results.
+
+\begin{thebibliography}{Van~Wyk~9999}
+\bibitem[Bentley~86]{bentley:lp}
+Jon L. Bentley, ``Programming Pearls,''
+{\sl Communications of the ACM} {\bf 29:5} (May~1986), 364--368, and
+{\bf 29:6} (June~1986), 471--483.
+\bibitem[Knuth~84]{knuth:literate-programming}
+Donald E. Knuth, ``Literate Programming,'' {\sl The Computer Journal}
+{\bf 27:2} (1984), 97--111.
+\bibitem[Levy~87]{levy:cweb}
+Silvio Levy, ``{\tt WEB} Adapted to C, Another Approach,''
+ {\sl TUGBoat} {\bf 8:1} (1987), 12--13.
+\bibitem[Van~Wyk~87]{cvw:loom}
+Christopher J. Van~Wyk, ``Literate Programming,''
+{\sl Communications of the ACM} {\bf 30:7} (July~1987), 593--599, and
+{\bf 30:12} (December~1987), 1000--1010.
+\end{thebibliography}
+
+------------------------------------------------------------------------
+2. Tgrind
+------------------------------------------------------------------------
+
+From: Ken Yap <ken@rochester.arpa>
+
+Several people have asked about including program source in TeX
+documents. I believe the most general approach is to use a utility like
+tgrind (TeX analog of vgrind). One specifies the language to be
+processed (so that tgrind can detect keywords). Tgrind converts tabs
+into the appropriate spacing (generates things like \tab{24} for 3
+tabs), boldens keywords, prints quoted strings in typewriter font,
+prints comments in italics, and other nice things. All these goodies
+are customizable. This requires an extra pass, but the preprocessing
+is quite fast.
+
+Tgrind is on the Unix TeX tape, in the directory TeXcontrib/van. It was
+written by Van Jacobson of LBL. Unfortunately it is Unix specific, but
+I think equivalents for other OS are no problem. Heck, just take your
+favourite pretty-printer and generate TeX instead of prettified
+output.
+
+Ken
+
+tgrind - grind nice program listings using TeX or LaTeX
+
+Tgrind formats program sources in a nice style using TeX.
+Comments are placed in italics, keywords in bold face and
+strings in typewriter font. Source file line numbers appear
+in the right margin (every 10 lines). The start of a
+function is indicated by the function name in large type in
+the right margin.
+
+In regular mode tgrind processes its input file(s) and
+passes them to TeX for formating and output.
+
+In format mode (i.e., when the flag is used), tgrind
+processes its input file(s) and writes the result to
+standard output. This output can be saved for later
+editting, inclusion in a larger document, etc.
+
+Currently known are
+ PASCAL, RATFOR, Modula-2, MODEL, C, ISP, Yacc,
+ Prolog, Icon, TeX, CSH, and Bourne Shell .
+
+Van Jacobson, Lawrence Berkeley Laboratory (based on
+"vgrind" by Dave Presotto & William Joy of UC Berkeley).
+------------------------------------
+Jerry Leichter improved tgrind. His version is available from
+venus.ycc.yale.edu in [.TGRIND].
+
+I've added some functionality to Jerry's version of tgrind and called
+it lgrind, as it only really works with LaTeX (as does Jerry's).
+Essentially, what I did was to add a facility for having fragments of
+code in comments (a la WEB) and to improve the embedded mode, where
+lgrind filters a LaTeX file with embedded chunks of code.
+
+I was going to release lgrind by itself, but now it's going to be part
+of Pretty!, a suite of prettyprinting programs by Joerg `joke'
+Heitkoetter (heitkoet@gorbi.informatik.uni-dortmund.de), who writes:
+ Pretty! currently consists of Modula2LaTeX (c.s.m.vol22i79-81), lgrind
+ and C++2LaTeX, plus a library for writing indentation tools like the
+ BSD indent (which might be rewritten by me for BSD4.4), plus low level
+ stuff like expand/unexpand(1) tools, etc.
+ I already made a proposal to FSF to call it "GNU Pretty!", we'll see...
+
+/George
+________________
+George V. Reilly `Georges Cinq' gvr@cs.brown.edu +1 (401) 863-7693
+uunet!brunix!gvr gvr@browncs.bitnet Box 1910, Brown U, Prov, RI 02912
+------------------------------------
+I hope you got George V Reilly's addendum to your "Currently available
+tools for program documentation" list, I hope to alpha release
+"Pretty! -- Utilities for Typesetting Formal Languages" during the
+next weeks...
+
+It contains LAGRiND, which is based on Van Jacobsen's tgrind, Jerry
+Leichter's update to tgrind, and some ideas developed by George's group at
+Brown University. It will make *any* tgrind version obsolete, because
+you can emulate the older versions with a switch.
+
+Pretty! (the ! belongs the the logo) is a collection of tools of the
+following kind:
+
+ 1. formatters (BSD indent)
+ 2. typesetters (LaGRiND, Modula2LaTeX, C++2LaTeX)
+ 3. low level utilities (expand/unexpand)
+
+Pretty! was much inspired by suite's like Rich Murphey's GNU Graphics, and
+Jef Poskanzer's PBM+. I hope Pretty! will be the a kind of clearing house
+for this special usage of LaTeX/TeX usage. We'll see.
+
+Thanx again and so long
+
+ -joke
+
+--
+Joerg Heitkoetter
+Systems Analysis Group
+University of Dortmund, Germany
+(heitkoet@gorbi.informatik.uni-dortmund.de).
+
+------------------------------------------------------------------------
+3. C2latex
+------------------------------------------------------------------------
+
+From: ramsdell@celebes.mitre.org (John D. Ramsdell)
+Subject: c2latex--Simple Support for Literate Programming in C
+
+C2latex provides simple support for literate programming in C. Given
+a C source file in which the comments have been written in LaTeX,
+c2latex converts the C source file into a LaTeX source file. It can
+be used to produce typeset listings of C programs and/or documentation
+associated with the program.
+
+The C source given to c2latex usually has the following form. It
+starts with a large comment containing LaTeX commands that start a
+document along with any initial text. Then there is a sequence of
+comment and code pairs, with the comment explaining the code to
+follow. The source file is ended by a comment containing LaTeX
+commands that finish the document.
+
+C2latex produces LaTeX source by implementing a small number of rules.
+A C comment that starts at the beginning of a line is copied
+unmodified into the LaTeX source file. Otherwise, non-blank lines are
+surrounded by a pair of formatting commands (\begin{flushleft} and
+\end{flushleft}), and the lines are separated by \\*. Each non-blank
+line is formatted using LaTeX's \verb command, except comments within
+the line are formatted in an \mbox.
+
+The c2latex program is written in ANSI C and can be processed by
+c2latex to produce LaTeX source containing a typeset listing of
+itself. It has a copyright similar to those distributed with GNU
+software. c2latex is available from me as a shar file via electronic
+mail. If there is enough interest, I will request that the sources be
+placed on a public server.
+
+John
+
+------------------------------------------------------------------------
+4. C++2latex
+------------------------------------------------------------------------
+
+The program c++2latex converts ANSI-C/C++ programs into LaTeX source.
+
+It requires flex which can be found on various ftp sites,
+ e.g. prep.ai.mit.edu. For those without flex and without the possibility
+to get one, I can email the flex'ed program.
+
+Please notice that this program is under GNU Copyleft.
+
+ DESCRIPTION
+
+c++2latex is a tool for generating LateX source from ANSI-C
+or C++ programs. It recogizes all keywords, strings, and
+comments. These recognized parts can be set in different
+fonts. c++2latex can generate complete LaTeX files which
+can directly passed through latex or parts of LaTeX files
+which can be included in other files (either direct or by
+the \input or \include commands). The output filename is
+searched in various steps. First, if the {-o,+output} flag
+is given, the output is written to the file pointed to by
+the value of this flag. If the {-t,+pipe} option is given,
+the output is written to stdout. (It is an error to specify
+both options together.) If none of this options but an input
+pathname is given, the output is written to a file who's
+name is the last component of the input pathname with the
+substituted or else added suffix '.tex'. If the input is
+read from stdin and none of the above options is given, the
+output is written to '<program-name>.tex' with <program-
+name> being the name of this program.
+
+------------------------------------------------------------------------
+5. Cprog macros
+------------------------------------------------------------------------
+
+The cprog macros allow programs in C, C++, Pascal, and Modula-2 to be
+included directly into TeX documents. Program text is set in a Roman
+font, comments in slanted, and strings in typewriter. Operators such as
+<= are optionally combined into single symbols like $\le$. Keywords are
+*not* emphasised---I find this ugly and distracting. (By purest
+coincidence it would also be very hard to do.)
+
+These macros can be \input in plain TeX or used as a style file in LaTeX.
+They provide a convenient alternative to tgrind, particularly for program
+fragments embedded in documents. Full instructions for use appear in the
+macro package itself.
+
+
+\'Eamonn McManus <emcmanus@cs.tcd.ie> <emcmanus%cs.tcd.ie@cunyvm.cuny.edu>
+
+This allows C programs to be formatted directly by TeX. It can be
+invoked by \cprogfile{filename} or (in LaTeX) \begin{cprog} ...
+\end{cprog} or (in plain TeX) \cprog ... \end{cprog}. In LaTeX, the
+alternative form \begin{cprog*} is allowed, where spaces in C strings
+are printed using the `square u' character (like LaTeX {verbatim*}).
+In plain TeX, you have to use \csname cprog*\endcsname for this (sorry).
+If you are using \cprogfile, say \cprogttspacetrue beforehand if you
+want this effect.
+
+The formatting is (necessarily) simple. C text is set in a normal Roman
+font, comments in a slanted font, and strings in a typewriter font, with
+spaces optionally made visible as the `square u' symbol. Tabs are
+expanded to four spaces (this does not look good when comments are
+aligned to the right of program text). Some pairs of input characters
+appear as single output characters: << <= >> >= != -> are respectively
+TeX's \ll \le \gg \ge \ne \rightarrow. Say \cprogpairsfalse to disable
+this.
+
+You can escape to TeX within cprog text by defining an escape character.
+The character @ is suitable for C and Pascal. I have not tested other
+characters so they may interact badly with their existing definitions here.
+To define @ as the escape character, do \cprogescape@. Then within text
+you can do @ followed by TeX commands. These commands will be in a TeX
+group with the \catcodes of \{}% as normal. The commands are terminated
+by a newline, which is not considered part of the program text.
+
+The fonts below can be changed to alter the setting of the various parts
+of the program. The \cprogbaselineskip parameter can be altered to
+change the line spacing. LaTeX's \baselinestretch is taken into account
+too. The indentation applied to the whole program is \cprogindent,
+initially 0. Before and after the program there are skips of
+\beforecprogskip and \aftercprogskip; the default values are \parskip
+and 0 respectively (since there will often be a \parskip after the
+program anyway).
+
+If the source text is Pascal or Modula-2, say \pascaltrue or \modulatrue
+(respectively) before formatting it. This makes (* *) be recognised for
+comments instead of /* */. Braces {} are also recognised for Pascal.
+\pascalfalse or \modulafalse as appropriate restores the default of C.
+
+This package works by making a large number of characters active. Since
+even spaces are active, it is possible to examine the next character in
+a macro by making it a parameter, rather than using \futurelet as one
+would normally do. This is more convenient, but the coding does mean
+that if the next character itself wants to examine a character it may
+look at a token from the macro rather than the input text. I think that
+all cases that occur in practice have been looked after.
+
+The macros could still do with some work. For example, the big macro
+defined with [] taking the place of {} could be recoded to use {} and so
+be more legible. The internal macros etc should have @ in their names,
+and should be checked against LaTeX macros for clashes.
+
+------------------------------------------------------------------------
+6. Program environment
+------------------------------------------------------------------------
+\documentstyle[program2]{article}
+\oddsidemargin 10mm \evensidemargin 10mm
+\marginparwidth 20mm \marginparsep 7pt
+\topmargin 0mm \headheight 12pt \headsep 1cm \footheight 12pt \footskip 30pt
+\textheight 220mm \textwidth 147mm \columnsep 10pt \columnseprule 0pt
+\def\lijn{\rule{\textwidth}{1pt}}
+\begin{document}
+\title{How to layout a (Pascal-)program in \LaTeX}
+\author{Rein Smedinga \\
+{\small department of computing science, p.o.box 800, 9700 AV Groningen }\\
+{\small tel. 050--633937 (633939), email: \verb!rein @cs.rug.nl!}}
+\maketitle
+\def\framed#1{\framebox[\textwidth][l]{\vbox{#1}}}
+\def\bep{\begin{program}\skipprog}% begin programtext
+\def\eep{\end{program}\noindent}% end programtext
+
+In \TeX\ or \LaTeX\ is it possible, but difficult, to create a nice layout
+for programs. The easiest way is to use the \verb!verbatim! environment.
+The layout is then copied from the input file. In most books a program
+(e.g., a PASCAL-program) is displayed using boldface reserved words,
+using math-italic for statements and using teletype fonts for string
+representations. Without extra equipment this can be done in \TeX\ as
+well as in \LaTeX\ using a \verb!tabbing!-environment.
+Of course, each font choice
+should be made explicitly, e.g., you must say \verb!{\bf begin}! to
+create a boldface begin-symbol and \verb!$x:=x+1$! to denote an
+assignment. Furthermore, the user is responsible for setting the tabs and
+jumping to the right ones. This is far from being user-friendly.
+
+The \verb!program!-environment tries to be of some help while displaying
+program-texts. It contains a number of macros of the form \verb!\BEGIN!,
+\verb!\PROCEDURE! and alike that not only put down a boldface begin-
+or procedure-symbol but also sets and jumps to the right tabs. Using
+the \verb!program! environment from the \verb!program2!-style file
+also automatically puts the statements
+in math-mode (you do not have to use \verb!$!-signs anymore).
+
+------------------------------------------------------------------------
+A similar style:
+
+program.sty: a LaTeX style file for typesetting algorithms.
+Copyright (C) 1991 Martin Ward
+
+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.
+
+This is the "program" style option which sets up the
+program and programbox environments,
+keywords for programs and a few goodies.
+NOTE: Within the program environment:
+(1) Newlines are significant.
+(2) Each line is in math mode, so for example spaces in the input
+ file are not significant.
+(3) \\ within a line causes a linebreak in the output.
+
+We also define a "programbox" environment which typesets a program in a box.
+Useful for keeping a piece of code on one page or for typesetting small
+programs in running text.
+We also redefine \( and \) as \begin{programbox} and \end{programbox}.
+The \tab and \untab commands are defined to have no effect while outside
+a program environment, hence a single-line program can be typeset in
+maths mode without the overhead associated with programbox.
+
+------------------------------------------------------------------------
+7. Scheme
+------------------------------------------------------------------------
+
+From: John D. Ramsdell <ramsdell%linus@mitre-bedford.ARPA>
+Subject: SchemeTeX---Simple support for literate programming in Lisp.
+
+SchemeTeX provides simple support for literate programming in any
+dialect of Lisp on Unix. Originally created for use with Scheme, it
+defines a new source file format which may be used to produce LaTeX
+code or Lisp code. Roughly speaking, LaTeX formats Lisp code in a
+verbatum-like environment, and it formats Lisp comments in an ordinary
+environment.
+
+SchemeTeX is available via anonymous FTP from linus (192.12.120.51) in
+the shar file named "pub/schemeTeX.sh". Included is an operating
+system independent version for the T dialect of Lisp.
+
+John
+
+------
+From: dorai@tone.rice.edu (Dorai Sitaram)
+Subject: typesetting Scheme code
+
+I wrote something called SLaTeX that allows listings of Scheme code in
+LaTeX without restricting it to the usual monospace typewriter font
+supported by other code typesetters.
+
+I've placed the current version in the titan.rice.edu's anonymous ftp
+area: get public/slatex.sh.
+
+SLaTeX decides which tokens should be, say, boldfaced, italicized, or
+sansserifed, pretty much along the style of the Little Lisper [1].
+(The user can completely control this default decision process, so
+much so that he can flip the fonts around, add new fonts, or even do
+something silly like make everything come out in typewriter -- i.e.,
+turn the program into a no-op.)
+
+I'd been leery of distributing SLaTeX before because of the frequent
+updating that it's undergone following the Rice Scheme-and-similar-
+language users' lively demands for bells and whistles, e.g.,
+
+o allowing arbitrarily positionable displays, boxed code, in-text code,
+ and directly inputing actual Scheme files;
+
+o getting little pockets of LaTeX text or mathmode into the Scheme
+ code, for readable Schemelike pseudocode (useful for
+ expository papers and class handouts);
+
+o making it learn automatically that a macro definition implies that
+ keyword should henceforth be boldfaced, etc.
+
+At any time, the ftp site will contain the most recent code. The shar
+file contains the Scheme source (Ch*z, but should carry over to other
+Schemes with minor changes), a shellscript that piggybacks the
+codesetter on to LaTeX, the requisite LaTeX style file, installation
+instructions, a manual in LaTeX, a man page, and a copyleft. The
+first 2 sections in the manual suffice for most uses, with fine tuning
+being described later. (The code, as of now, contains more fine
+tuning than documented -- I'll update the docs when I next get time.)
+
+This is free(ly distributable) software, and hence no warranty, though
+I'll be glad to field bug and other reports.
+
+
+[1] D.P. Friedman and M. Felleisen, _The Little Lisper_, Science
+Research Associates (3e), 1989, and The MIT Press, 1987.
+
+------------------------------------------------------------------------
+8. Ada.
+------------------------------------------------------------------------
+
+See TUGboat 10#1, April 1989
+ Sriram Sankar APE -- A set of TeX macros to format Ada
+ programs
+
+I have developed a set of macros to do exactly this for Ada programs.
+To get more details on these macros, read the report in the April issue
+of TUGBoat, or the Nov/Dec issue of Ada Letters (both in 1989).
+
+The macros are available by anonymous ftp to anna.stanford.edu in the
+pub directory (I think). I can send them to you if you are willing
+to cover the costs.
+
+Sriram.
+
+See also:
+ GUTenberg'90
+ May 15-18, 1990
+University Paul Sabatier, Toulouse, FRANCE
+
+Typesetting ADA programs (P. Naudin, C. Quitte)
+
+------------------------------------------------------------------------
+9. Modula-2/Pascal
+------------------------------------------------------------------------
+
+m2latex - a Modula-2 to LaTeX converter
+
+m2latex is a tool for generating LaTeX sources from Pascal
+or Modula-2 It recogizes all keywords, strings, and com-
+ments. These recognized parts can be typeset in different
+fonts. m2latex can generate complete LaTeX files which can
+pass directly through latex(1) or parts of LaTeX files which
+can be included in other files (either direct or by the
+\input or \include commands).
+
+The output filename is searched in various steps. First, if
+the {-o,+output} flag is given, the output is written to the
+file pointed to by the value of this flag. If the {-p,+pipe}
+option is given, the output is written to stdout. (It is an
+error to specify both options together.) If none of these
+options but an input filename is given, the output is writ-
+ten to a file who's name is the last component of the input
+filename with the added suffix '.tex'.
+
+* Copyright (C) 1991 Joerg Heitkoetter
+* Systems Analysis Group, University of Dortmund, Germany.
+* (heitkoet@gorbi.informatik.uni-dortmund.de).
+(distributed under GNU copyleft)
+
+------------------------------------------------------------------------
+10. Sundry.
+------------------------------------------------------------------------
+
+From: rosenber@ra.abo.fi (Robin Rosenberg INF)
+Subject: Re: Typesetting programming languages in LaTeX
+
+About two years ago I wrote a program that converts programs to TeX.
+The program sets keywords in boldface (or any font you select) using a
+data file to find out which strings are keywords and how to skip
+comments. I have data files for Modula-2, C, C++, Pascal, Occam, Beta,
+and some more. The program is written in C (under VMS) and could well
+be improved. However it does what I want it to do, it makes programs
+_look_ nice in listing. As said it translates to TeX and not LaTex but that is no big deal to change I'd guess.
+
+If you need this program send a mail to rosenber@ra.abo.fi. mail
+
+Robin Rosenberg
+
+------------------------------------------------------------------------
+I have an SED script and Pascal environment for LaTeX that follows
+the standard Algol 60 style for setting Pascal text. The SED
+script translates everything between \begin{pascal} and \end{pascal}
+in various ways that the pascal environment understands. The only
+problem with the thing is that indenting must be in multiples of
+4 spaces, but I've used it for a number of publications without
+hearing any complaints about my awkward indenting style.
+
+In any case, I strongly recommend the notion of environments for
+language types, as opposed to the various grind programs. It would
+be nice to have a standard set of environment parameters to control
+things like keyword font so language environments from different
+sources could be at least somewhat interchangable.
+
+ Doug Jones
+ jones@herky.cs.uiowa.edu
+
+------------------------------------------------------------------------
+% manpage.sty
+
+% Rong Chen (rchen@cs.uiuc.edu)
+% Department of Computer Science
+% University of Illinois at Urbana-Champaign
+% Urbana, IL 61801
+
+% Copyright (c) 1990 by Rong Chen
+% Permission to copy all or part of this work is granted, provided
+% that the copies are not made or distributed for resale, and that
+% the copyright notice and this notice are retained.
+%
+% THIS WORK IS PROVIDED ON AN "AS IS" BASIS. THE AUTHOR PROVIDES NO
+% WARRANTY WHATSOEVER, EITHER EXPRESS OR IMPLIED, REGARDING THE WORK,
+% INCLUDING WARRANTIES WITH RESPECT TO ITS MERCHANTABILITY OR FITNESS
+% FOR ANY PARTICULAR PURPOSE.
+
+% This style option is designed to work with the report document style
+% of LaTeX version 2.09. Use \documentstyle[11pt,manpage]{report}
+%
+% This LaTeX style file is similer to the UNIX troff man macros in format and
+% is specially tuned for documenting the C++ library that the author wrote.
+%
+% The commands that are created in the style file are:
+%
+% \begin{manpage}{Title}{Module}{Version} % see an example, all will be clear
+% \end{manpage} % end of manpage environment
+% \variable{#1} (e.g., \variable{int foo}) % with \medskip added
+% \variable*{#1} (e.g., \variable*{int bar})% no extra spacing
+% \function{#1} (e.g., \function{void demo(int dummy)}) % with \medskip added
+% \function*{#1} (e.g., \function*{void demo(int dummy)})% no extra spacing
+% \subtitle{#1} (e.g., \subtitle{AUTHOR}) % fit in the same line if possible
+% \subtitle*{#1} (e.g., \subtitle*{AUTHOR})% always break a newline
+% "#1" (e.g., "dummy_variable") % argument is in italic&unbreakable
+% \separator % draw a thin line to seperate suntitle from the text
+% \header{#1}{#2}{#3} % in case you want to have a header and
+% \footer{#1}{#2}{#3} % a footer outside of the manpage environment
+% \dq % print double quote character (")
+%
+% In the \function macro, data types and their dummy arguments are separated
+% by a space. So if you have a function like "int f(const int n)", you should
+% document it as \function{int f(const~int n)}. The argument n is optional.
+% In the \subtitle macro, two lines of text may be devided by "\\".
+---------------------------------------------------------------------------
+MAKEPROG
+---------------------------------------------------------------------------
+Another possibility, which comes very close to your suggestion, is
+J. Schrod's MAKEPROG. With this you can write plain-TeX or LaTeX documents
+with embedded program fragments (simply enclosed in \beginprog and
+\endprog), that will be typeset just verbatim. MAKEPROG extracts the program
+fragments from the source and joins them together (in linear order only).
+All in all, MAKEPROG has less capabilities than WEB, but is not limited to a
+given programming language. You can get it from the address above in the
+directory /soft/tex/utilities. I wrote an enhancement to MAKEPROG, that
+makes the layout of the documentation more WEB-like; if you are interested,
+I will mail it to you.
+
+Hans-Hermann Bode
+Arbeitsgruppe Systemforschung, Universit\"at Osnabr\"uck
+Tel.: (49)-541-9692545
+e-mail: HHBODE@DOSUNI1.BITNET
+
+------------------------------------------------------------------------
+CNOWEB:
+------------------------------------------------------------------------
+There's another C to plain TeX system, cnoweb, available from
+u.washington.edu in pub/tex/cnoweb.
+
+c-NO_WEB (a c program pretty printer)
+by Jim Fox, February 1987
+version 1.1, August 10, 1989
+version 1.2, October 30, 1989
+ fixed spacing after ?, :, etc.
+version 1.3, June 28, 1990
+ added OOdent and IIdent, added \|typewriter|
+version 1.4, January 4, 1991
+ allow /* and */ in strings
+
+-----------------------------------------------------------------
+
+The TeX input file is a c source program. It is assumed to have
+this structure:
+
+ /* comments ignored by c-no-web
+ \input cnoweb
+ \title{A one line title of the program (optional) }
+ \synopsis{Synopsis of the program (optional) }
+ \section{Name of the first section}
+ rest of comments */
+
+The rest of the file is normal c code.
+Within the title a \\ may be used to separate lines.
+
+Each major section begins with
+ /* \section{name of the section} .... */
+The section names are printed boldface, marked for reference in
+the page headline, and written to the table of contents.
+
+Each minor section begins with
+ /* \subsection{name of the subsection} .... */
+The subsection names are written to the table of contents.
+
+A new page can be forced by
+ /* \newpage */
+
+Code and other text containing special characters may be
+typed in text mode if it is bracked by *< ... >*
+e.g. /* *<inactive c-code>* */
+but this may not be used in a macro argument.
+
+You can print in bold by enclosing text in double quotes: \"text".
+You can print in typewriter by enclosing text in vertical bars: \|text|.
+You can print in italics by enclosing text in single quotes: \'text'.
+
+The file must end with \endc in a comment. e.g.,
+ ... last c code statement ...
+ /* \endc */
+------------------------------------------------------------------------
+--
+Piet* van Oostrum, Dept of Computer Science, Utrecht University,
+Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands.
+Telephone: +31 30 531806 Uucp: uunet!mcsun!ruuinf!piet
+Telefax: +31 30 513791 Internet: piet@cs.ruu.nl (*`Pete')
+
diff --git a/web/glasgow/lit2x-0.16/mkworld/Jmakefile b/web/glasgow/lit2x-0.16/mkworld/Jmakefile
new file mode 100644
index 0000000000..06d7716931
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/Jmakefile
@@ -0,0 +1,72 @@
+/*
+ * partain: from...
+ *
+ * $XConsortium: Jmakefile,v 1.7 89/12/12 12:37:28 jim Exp $
+ *
+ * This is used to recreate jmake. Makefile.BOOT is used to generate jmake
+ * if there is no Makefile in this directory (i.e., the first time).
+ */
+
+#define IHaveSubdirs
+
+/* just documents subdir */
+#define NoAllTargetForSubdirs
+#define NoInstallTargetForSubdirs
+#define NoTagTargetForSubdirs
+
+SUBDIRS = docs
+
+/* ------------------------- */
+
+SRCS_C = jmake.c ccjmake.c
+DEPLIBS =
+HEADERS = jmakemdep.h
+
+JCONFIGFILES = $(HEADERS) TEMPLATE.jm \
+ install-GEN.jm macros-GEN.jm \
+ plat-DEF.jm plat-TRIGGERS.jm \
+ plat-mipsriscos.jm plat-sun.jm plat-linux.jm plat-alpha.jm \
+ site-DEF.jm site.jm \
+ suffixes-GEN.jm utils-GEN.jm
+
+DEFINES = $(SIGNAL_DEFINES)
+
+all:: jmake jmkmf
+
+MsubNeededHere(jmkmf)
+
+/* override the usual rule */
+#undef JmakeNeededHere
+#define JmakeNeededHere(dummy) @@\
+Makefile:: jmake
+
+/* BUILDING =======================================================*/
+
+BuildPgmFromCFiles(jmake,jmake.o,,)
+
+/* modelled on X11R4's xmkmf (via DuBois) */
+MsubMakefileDependentProgramScriptTarget(PerlCmd,jmkmf,jmkmf.prl,/*no flags*/,/*Makefile*/)
+
+/* INSTALLATION ===================================================*/
+
+INSTDATADIR_MKWORLD = $(INSTDATADIR)/mkworld
+
+MakeDirectories(install,$(INSTBINDIR) $(INSTSCRIPTDIR) $(INSTDATADIR_MKWORLD))
+InstallBinaryTarget(jmake,$(INSTBINDIR))
+
+InstallMsubbedScriptTarget(PerlCmd,jmkmf,jmkmf.prl,$(INSTSCRIPTDIR))
+
+InstallScriptTarget(jrestoredeps,$(INSTSCRIPTDIR))
+
+jconfigfiles : $(JCONFIGFILES)
+InstallTarget(jconfigfiles)
+InstallMultNonExecTargets(jconfigfiles,$(JCONFIGFILES),$(INSTDATADIR_MKWORLD))
+
+/* OTHER STUFF ===================================================*/
+ExtraStuffToClean(ccjmake)
+
+ExtraStuffToBeVeryClean( ccjmake $(STD_VERY_CLEAN) $(JCONFIGFILES) )
+
+EtagsNeededHere(tags) /* need this to do "make tags" */
+ClearTagsFile()
+CTagsTarget( $(SRCS_C) $(JCONFIGFILES) )
diff --git a/web/glasgow/lit2x-0.16/mkworld/Makefile.BOOT b/web/glasgow/lit2x-0.16/mkworld/Makefile.BOOT
new file mode 100644
index 0000000000..908a5cb7ff
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/Makefile.BOOT
@@ -0,0 +1,80 @@
+#
+# WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+#
+# This is NOT an automatically generated Makefile! It is hand-crafted as a
+# bootstrap, may need editing for your system. The BOOTSTRAPCFLAGS variable
+# may be given at the top of the build tree for systems that do not define
+# any machine-specific preprocessor symbols.
+#
+
+BOOTSTRAPCFLAGS =
+PROJECTLABEL = none
+SETUPLABEL = std
+CDEBUGFLAGS =
+CFLAGS = $(BOOTSTRAPCFLAGS) $(CDEBUGFLAGS)
+SHELL = /bin/sh
+RM = rm -f
+MV = mv -f
+MAKE = make
+CLEAN_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a tags TAGS make.log
+NPROC = 1
+
+TOP = ..
+CURRENT_DIR = ./mkworld
+
+JMAKESRC = $(TOP)/mkworld
+JMAKE = $(JMAKESRC)/jmake
+
+JMAKE_CMD = $(JMAKE) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) $(BOOT_DEFINES)
+
+LIT2PGM = lit2pgm -q
+
+.SUFFIXES : .ljm .jm
+
+.ljm.jm:
+ $(RM) $@
+ $(LIT2PGM) $(LIT2PGMFLAGS) -o $@ $<
+ @chmod 444 $@
+
+all: jmake Makefile
+
+jmake::
+ @echo "making jmake with BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)"
+
+jmake:: ccjmake jmake.c
+ $(CC) -o jmake $(CFLAGS) jmake.c `./ccjmake`
+
+ccjmake: ccjmake.c
+ $(CC) -o ccjmake $(CFLAGS) ccjmake.c
+
+relink:
+ $(RM) jmake
+ $(MAKE) $(MFLAGS) jmake
+
+clean:
+ $(RM) ccjmake jmake
+ $(RM) \#*
+
+depend:
+
+
+# for manual use
+
+Makefile ::
+ -@if [ -f Makefile ]; then \
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(JMAKE_CMD)
+ @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi
+ @chmod 444 Makefile
+ @echo ==== The new Makefile is for\: ====
+ @$(MAKE) whoami
+
+tags:
+
+install:
+
+install_docs:
+
+Makefiles:
diff --git a/web/glasgow/lit2x-0.16/mkworld/Makefile.DUMMY b/web/glasgow/lit2x-0.16/mkworld/Makefile.DUMMY
new file mode 100644
index 0000000000..8bd7aa66bb
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/Makefile.DUMMY
@@ -0,0 +1,21 @@
+Makefile::
+
+Makefiles::
+
+depend::
+
+all::
+
+runtests::
+
+install::
+
+docs::
+
+install_docs::
+
+clean::
+
+veryclean::
+
+tags::
diff --git a/web/glasgow/lit2x-0.16/mkworld/PATCHLEVEL b/web/glasgow/lit2x-0.16/mkworld/PATCHLEVEL
new file mode 100644
index 0000000000..2136a5e328
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/PATCHLEVEL
@@ -0,0 +1 @@
+Glasgow `make world' configuration system, version 0.16, patchlevel 0
diff --git a/web/glasgow/lit2x-0.16/mkworld/README b/web/glasgow/lit2x-0.16/mkworld/README
new file mode 100644
index 0000000000..1bc06e06fc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/README
@@ -0,0 +1,26 @@
+This is the Glasgow "make world" configuration system. We always
+distribute as a component of another system (e.g., the Glasgow Haskell
+compiler), but it can be used separately.
+
+It is based on "imake" in the MIT distribution of the X Window System,
+as hacked on by Paul DuBois to support "multiple projects". None of
+those people would probably recognise it now.
+
+The instructions for using this system come with the main system (ghc,
+nofib, etc.) They may, however, aim you at the documentation here:
+
+ docs/mkworld_guide/mkw_guide.{dvi,info}
+ general user's guide
+
+ docs/mkworld_ref/mkw_ref.{dvi,info}
+ reference guide -- actually the ``make world''
+ source in literate form.
+
+ docs/<other> documents related to X11 `imake' or Paul
+ DuBois's variant, the ancestors of this
+ system.
+
+Bug reports and comments would be most welcome.
+
+Will Partain
+partain@dcs.glasgow.ac.uk
diff --git a/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.jm b/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.jm
new file mode 100644
index 0000000000..8fcd80bc73
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.jm
@@ -0,0 +1,199 @@
+# line 1 "TEMPLATE.ljm"
+# line 37 "TEMPLATE.ljm"
+#define YES 1
+#define NO 0
+
+#if __STDC__
+#define CAT2(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define CAT4(a,b,c,d) a##b##c##d
+#define CAT5(a,b,c,d,e) a##b##c##d##e
+#else
+#define CAT2(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d) a/**/b/**/c/**/d
+#define CAT5(a,b,c,d,e) a/**/b/**/c/**/d/**/e
+#endif /* not STDC */
+# line 66 "TEMPLATE.ljm"
+#include "plat-TRIGGERS.jm"
+
+/*# Platform-specific stuff was read from: PlatformFile */
+#include PlatformIncludeFile
+#include <plat-DEF.jm>
+# line 84 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include SITE_SETUP_FILE /* site-specific things for a setup of a project */
+#endif
+#include SITE_PROJECT_FILE /* site-specific things for a project */
+#endif /* Project != none */
+
+#include <site.jm> /* project-independent site-specific things */
+#include <site-DEF.jm> /* _defaults_ for site-specific things */
+# line 106 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include MACROS_SETUP_FILE
+#endif
+#include MACROS_PROJECT_FILE
+#endif /* Project != none */
+
+#include <macros-GEN.jm>
+# line 123 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include ONLY4_SETUP_FILE
+#endif
+#include ONLY4_PROJECT_FILE
+#endif /* Project != none */
+# line 132 "TEMPLATE.ljm"
+/*# Project identification -- name, version, and stuff */
+#ifndef ProjectName
+#define ProjectName NO_SPECIFIC_PROJECT
+#endif
+#ifndef ProjectVersion
+#define ProjectVersion NO_SPECIFIC_VERSION
+#endif
+PROJECTNAME = ProjectName
+PROJECTVERSION = ProjectVersion
+PROJECTLABEL = ProjectLabel
+SETUPLABEL = SetupLabel
+#ifdef HaveProjectMkworldDir
+PROJ_MKWORLD_DIR = ProjectMkworldDir
+#else
+PROJ_MKWORLD_DIR =
+#endif
+HOSTPLATFORM = HostPlatform
+/* HOSTPLATFORM: the platform we expect the thing we are building will run on. */
+
+/* BUILDPLATFORM: the platform we are building on NOW (if we can figure it out)
+ set by the platform-specific files
+*/
+# line 163 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include SUFFIXES_SETUP_FILE
+#endif
+#include SUFFIXES_PROJECT_FILE
+#endif /* Project != none */
+
+#include <suffixes-GEN.jm>
+# line 180 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include UTILS_SETUP_FILE
+#endif
+#include UTILS_PROJECT_FILE
+#endif /* Project != none */
+
+#include <utils-GEN.jm>
+# line 197 "TEMPLATE.ljm"
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include INSTALLATION_SETUP_FILE
+#endif
+#include INSTALLATION_PROJECT_FILE
+#endif /* Project != none */
+
+#include <install-GEN.jm>
+# line 214 "TEMPLATE.ljm"
+/* something so "all" is the first target... */
+all ::
+
+#include INCLUDE_JMAKEFILE
+# line 227 "TEMPLATE.ljm"
+/*# end of stuff from Jmakefile */
+/*# --------------------------- */
+/*# common end-of-Makefile rules -- (still) DO NOT EDIT !!! */
+/*
+ * These need to be here so that rules in Jmakefile occur first; the blank
+ * all is to make sure that an empty Jmakefile doesn't default to make clean.
+ */
+emptyrule::
+
+CleanTarget()
+
+VeryCleanTarget()
+
+#ifndef IHaveSpecialMakefileTarget
+MakefileTarget()
+#endif
+
+/* tags not in by default: you have to ask: TagsTarget() */
+tags::
+
+#ifdef MakefileAdditions
+MakefileAdditions()
+#endif
+
+
+#ifdef IHaveSubdirs
+/*###########################################################################
+ # rules for building in SUBDIRS - DO NOT EDIT !!!
+*/
+#ifndef NoAllTargetForSubdirs
+DoAllinSubdirs($(SUBDIRS))
+#endif
+#ifndef NoDocsTargetForSubdirs
+DoDocsinSubdirs($(SUBDIRS))
+#else
+docs:: /* nothing */
+#endif
+#ifndef NoRunTestsTargetForSubdirs
+RunTestsSubdirs($(SUBDIRS))
+#else
+runtests::
+ @echo "runtests in $(CURRENT_DIR) done"
+#endif
+#ifndef NoInstallTargetForSubdirs
+InstallSubdirs($(SUBDIRS))
+#else
+install::
+ @echo "install in $(CURRENT_DIR) done"
+#endif
+#ifndef NoInstallDocsTargetForSubdirs
+InstallDocsSubdirs($(SUBDIRS))
+#else
+install_docs::
+ @echo "install_docs in $(CURRENT_DIR) done"
+#endif
+#ifndef NoDependTargetForSubdirs
+DependSubdirs($(SUBDIRS))
+#else
+depend::
+ @echo "depend in $(CURRENT_DIR) done"
+#endif
+#ifndef NoTagTargetForSubdirs
+TagSubdirs($(SUBDIRS))
+#endif
+
+CleanSubdirs($(SUBDIRS))
+VeryCleanSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+
+#else
+/*###########################################################################
+ # empty rules for directories that do not have SUBDIRS - DO NOT EDIT !!!
+*/
+/* clean and veryclean rules not given here because they're added above... */
+
+docs::
+
+tags::
+ @echo "tags in $(CURRENT_DIR) done"
+
+runtests::
+ @echo "runtests in $(CURRENT_DIR) done"
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install_docs::
+ @echo "install_docs in $(CURRENT_DIR) done"
+
+Makefiles::
+
+depend::
+ @echo "depend in $(CURRENT_DIR) done"
+
+#endif /* if subdirectory rules are needed */
diff --git a/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.ljm b/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.ljm
new file mode 100644
index 0000000000..43fd2a404b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/TEMPLATE.ljm
@@ -0,0 +1,322 @@
+%************************************************************************
+%* *
+\section[mkworld-TEMPLATE]{Main ``mkworld'' template; slurps in ...}
+%* *
+%************************************************************************
+
+\begin{pseudocode}
+#define JMAKE_TEMPLATE "TEMPLATE.jm"
+#define INCLUDE_JMAKEFILE <Jmakefile>
+#define SetupLabel std
+#define SetupIsStd 1
+#define ProjectLabel none
+#define ProjectIsNone 1
+#define SITE_SETUP_FILE <site-none-std.jm>
+#define SITE_PROJECT_FILE <site-none.jm>
+#define ONLY4_SETUP_FILE <only4-none-std.jm>
+#define ONLY4_PROJECT_FILE <only4-none.jm>
+#define SUFFIXES_SETUP_FILE <suffixes-none-std.jm>
+#define SUFFIXES_PROJECT_FILE <suffixes-none.jm>
+#define MACROS_SETUP_FILE <macros-none-std.jm>
+#define MACROS_PROJECT_FILE <macros-none.jm>
+#define UTILS_SETUP_FILE <utils-none-std.jm>
+#define UTILS_PROJECT_FILE <utils-none.jm>
+#define INSTALLATION_SETUP_FILE <install-none-std.jm>
+#define INSTALLATION_PROJECT_FILE <install-none.jm>
+\end{pseudocode}
+
+
+This is the main template that is ``filled in'' by the @mkworld@
+configuration system, to create a Makefile.
+
+This whole scheme is derived from the fine work on a ``multi-project
+Imake'' by Paul DuBois at the Wisconsin Regional Primate Research Center.
+
+First some pervasive, needed-everywhere definitions:
+\begin{code}
+#define YES 1
+#define NO 0
+
+#if __STDC__
+#define CAT2(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define CAT4(a,b,c,d) a##b##c##d
+#define CAT5(a,b,c,d,e) a##b##c##d##e
+#else
+#define CAT2(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d) a/**/b/**/c/**/d
+#define CAT5(a,b,c,d,e) a/**/b/**/c/**/d/**/e
+#endif /* not STDC */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-platform]{Platform-specific things}
+%* *
+%************************************************************************
+
+@plat-TRIGGERS.jm@ uses the ``trigger'' symbols to decide what
+platform-specific stuff to drag in; then it is so dragged.
+
+Defaults for any platform-ish things can be defined in @plat-GEN.jm@,
+with overrides in the individual platform-configuration files.
+
+\begin{code}
+#include "plat-TRIGGERS.jm"
+
+/*# Platform-specific stuff was read from: PlatformFile */
+#include PlatformIncludeFile
+#include <plat-DEF.jm>
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-site]{Site-specific things}
+%* *
+%************************************************************************
+
+Site-specific configuration stuff is, by definition, to override
+default definitions to satisfy the needs of a particular ((setup of a)
+project at a) site.
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include SITE_SETUP_FILE /* site-specific things for a setup of a project */
+#endif
+#include SITE_PROJECT_FILE /* site-specific things for a project */
+#endif /* Project != none */
+
+#include <site.jm> /* project-independent site-specific things */
+#include <site-DEF.jm> /* _defaults_ for site-specific things */
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-macros]{Main mkworld CPP macros}
+%* *
+%************************************************************************
+
+These don't generate any Makefile text, just define macros to be used
+later. They have to come early, notably before the ONLY4 stuff.
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include MACROS_SETUP_FILE
+#endif
+#include MACROS_PROJECT_FILE
+#endif /* Project != none */
+
+#include <macros-GEN.jm>
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-only4]{Extra things ``only for'' a specific project}
+%* *
+%************************************************************************
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include ONLY4_SETUP_FILE
+#endif
+#include ONLY4_PROJECT_FILE
+#endif /* Project != none */
+\end{code}
+
+\begin{code}
+/*# Project identification -- name, version, and stuff */
+#ifndef ProjectName
+#define ProjectName NO_SPECIFIC_PROJECT
+#endif
+#ifndef ProjectVersion
+#define ProjectVersion NO_SPECIFIC_VERSION
+#endif
+PROJECTNAME = ProjectName
+PROJECTVERSION = ProjectVersion
+PROJECTLABEL = ProjectLabel
+SETUPLABEL = SetupLabel
+#ifdef HaveProjectMkworldDir
+PROJ_MKWORLD_DIR = ProjectMkworldDir
+#else
+PROJ_MKWORLD_DIR =
+#endif
+HOSTPLATFORM = HostPlatform
+/* HOSTPLATFORM: the platform we expect the thing we are building will run on. */
+
+/* BUILDPLATFORM: the platform we are building on NOW (if we can figure it out)
+ set by the platform-specific files
+*/
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-suffixes]{Suffix rules}
+%* *
+%************************************************************************
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include SUFFIXES_SETUP_FILE
+#endif
+#include SUFFIXES_PROJECT_FILE
+#endif /* Project != none */
+
+#include <suffixes-GEN.jm>
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-utils]{``Utilities''}
+%* *
+%************************************************************************
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include UTILS_SETUP_FILE
+#endif
+#include UTILS_PROJECT_FILE
+#endif /* Project != none */
+
+#include <utils-GEN.jm>
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-installation]{Installation stuff}
+%* *
+%************************************************************************
+
+\begin{code}
+#if ProjectIsNone == NO
+#if SetupIsStd == NO
+#include INSTALLATION_SETUP_FILE
+#endif
+#include INSTALLATION_PROJECT_FILE
+#endif /* Project != none */
+
+#include <install-GEN.jm>
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-dir-specific]{Bring in directory-specific stuff (@Jmakefile@)}
+%* *
+%************************************************************************
+
+\begin{code}
+/* something so "all" is the first target... */
+all ::
+
+#include INCLUDE_JMAKEFILE
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-template-end-Makefile]{Common end-of-Makefile stuff}
+%* *
+%************************************************************************
+
+\begin{code}
+/*# end of stuff from Jmakefile */
+/*# --------------------------- */
+/*# common end-of-Makefile rules -- (still) DO NOT EDIT !!! */
+/*
+ * These need to be here so that rules in Jmakefile occur first; the blank
+ * all is to make sure that an empty Jmakefile doesn't default to make clean.
+ */
+emptyrule::
+
+CleanTarget()
+
+VeryCleanTarget()
+
+#ifndef IHaveSpecialMakefileTarget
+MakefileTarget()
+#endif
+
+/* tags not in by default: you have to ask: TagsTarget() */
+tags::
+
+#ifdef MakefileAdditions
+MakefileAdditions()
+#endif
+
+
+#ifdef IHaveSubdirs
+/*###########################################################################
+ # rules for building in SUBDIRS - DO NOT EDIT !!!
+*/
+#ifndef NoAllTargetForSubdirs
+DoAllinSubdirs($(SUBDIRS))
+#endif
+#ifndef NoDocsTargetForSubdirs
+DoDocsinSubdirs($(SUBDIRS))
+#else
+docs:: /* nothing */
+#endif
+#ifndef NoRunTestsTargetForSubdirs
+RunTestsSubdirs($(SUBDIRS))
+#else
+runtests::
+ @echo "runtests in $(CURRENT_DIR) done"
+#endif
+#ifndef NoInstallTargetForSubdirs
+InstallSubdirs($(SUBDIRS))
+#else
+install::
+ @echo "install in $(CURRENT_DIR) done"
+#endif
+#ifndef NoInstallDocsTargetForSubdirs
+InstallDocsSubdirs($(SUBDIRS))
+#else
+install_docs::
+ @echo "install_docs in $(CURRENT_DIR) done"
+#endif
+#ifndef NoDependTargetForSubdirs
+DependSubdirs($(SUBDIRS))
+#else
+depend::
+ @echo "depend in $(CURRENT_DIR) done"
+#endif
+#ifndef NoTagTargetForSubdirs
+TagSubdirs($(SUBDIRS))
+#endif
+
+CleanSubdirs($(SUBDIRS))
+VeryCleanSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+
+#else
+/*###########################################################################
+ # empty rules for directories that do not have SUBDIRS - DO NOT EDIT !!!
+*/
+/* clean and veryclean rules not given here because they're added above... */
+
+docs::
+
+tags::
+ @echo "tags in $(CURRENT_DIR) done"
+
+runtests::
+ @echo "runtests in $(CURRENT_DIR) done"
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install_docs::
+ @echo "install_docs in $(CURRENT_DIR) done"
+
+Makefiles::
+
+depend::
+ @echo "depend in $(CURRENT_DIR) done"
+
+#endif /* if subdirectory rules are needed */
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/ccjmake.c b/web/glasgow/lit2x-0.16/mkworld/ccjmake.c
new file mode 100644
index 0000000000..08909fa70a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/ccjmake.c
@@ -0,0 +1,21 @@
+/*
+ * $XConsortium: ccjmake.c,v 1.12 89/10/16 12:09:23 jim Exp $
+ *
+ * Warning: This file must be kept as simple as posible so that it can
+ * compile without any special flags on all systems. Do not touch it unless
+ * you *really* know what you're doing. Make changes in jmakemdep.h, not here.
+ */
+
+#define CCJMAKE /* only get jmake_ccflags definitions */
+#include "jmakemdep.h" /* things to set when porting jmake */
+
+#ifndef jmake_ccflags
+#define jmake_ccflags "-O"
+#endif
+
+main()
+{
+ write(1, jmake_ccflags, sizeof(jmake_ccflags) - 1);
+ exit(0);
+}
+
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/Jmakefile b/web/glasgow/lit2x-0.16/mkworld/docs/Jmakefile
new file mode 100644
index 0000000000..1158494761
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/Jmakefile
@@ -0,0 +1,9 @@
+#define IHaveSubdirs
+
+/* just documents here */
+#define NoAllTargetForSubdirs
+#define NoInstallTargetForSubdirs
+#define NoTagTargetForSubdirs
+
+SUBDIRS = mkworld_guide \
+ mkworld_ref
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/appendix-X11R4.ms b/web/glasgow/lit2x-0.16/mkworld/docs/appendix-X11R4.ms
new file mode 100644
index 0000000000..112722b468
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/appendix-X11R4.ms
@@ -0,0 +1,2413 @@
+.\" format with
+.\" tbl % | xroff -ms | lpr
+.\"
+.\" revision date - change whenever this file is edited
+.ds Rd 28 January 1991
+.\" document revision number - change each time document is released
+.ds Rn 1.01
+.\"
+.nr PO 1.2i \" page offset 1.2 inches
+.nr PD .7v \" inter-paragraph distance
+.\"
+.EH 'Imake in X11R4'- % -''
+.OH ''- % -'Imake in X11R4'
+.OF 'Revision date:\0\0\*(Rd'\s+1\*-MORE DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.EF 'Revision date:\0\0\*(Rd'\s+1\*-MORE DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.\"
+.\"
+.\" I - italic font (taken from -ms and changed)
+.de I
+.nr PQ \\n(.f
+.if t \&\\$3\\f2\\$1\\fP\&\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\c
+.if n .if \\n(.$>1 \&\\$2
+..
+.\" start block. LP gives a bit extra space. Can say .Ds .IP C, etc.
+.de Ds
+.if \\n(.$<1 .LP
+.if \\n(.$>=1 \\$1
+.if \\n(.$<2 .DS
+.if \\n(.$>=2 .DS \\$2 \\$3 \\$4 \\$5
+..
+.\" end block. If arg is given, it replaces the .LP (e.g., .De .IP).
+.de De
+.DE
+.if \\n(.$<1 .LP
+.if \\n(.$>=1 \\$1 \\$2 \\$3 \\$4 \\$5
+..
+.\" if the Sy definition changes, there are four symbols which had to be
+.\" manually formatted and which need to be changed manually,
+.\" UNCOMPRESSFILT, BDFTOSNFFILT, SHELLPATH, ZBDFTOSNFFILT
+.de Sy \" symbol definition
+.br
+.ta 6iR
+\fB\\$1\fR \\$3
+.br
+\0\0default: \\$2
+..
+.de Ru \" imake rule
+.br
+.ne 3v
+.B \\$1
+..
+.NH
+Appendix
+.LP
+.I cpp
+symbols and
+.I make
+variables defined in the X configuration files are listed and described here.
+Much of this information can be found in those files and in
+.I mit/config/README .
+.LP
+There are a number of places where I confess ignorance.
+If you fill me in on the missing pieces, I'll revise this document.
+.LP
+Besides symbols used for rule macros, symbols may be classed in
+three categories.
+Some are used as booleans and are defined as YES or NO.
+Some are simply defined as nothing or left undefined.
+Boolean and defined/not-defined symbols are rarely if ever
+associated with variables appearing in
+.I Makefiles ;
+rather, they are used for control purposes to modify the configuration
+and build process.
+.LP
+The other symbols are general-purpose, usually (but not always)
+having a value that is assigned to some
+.I Makefile
+variable.
+The value may be empty (that is, the symbol may be defined as nothing):
+.Ds
+.ta 1i 2i
+#define \fIsymbol\fR /* as nothing */
+.De
+The descriptions below give symbol names, and their defaults and
+symbol class where applicable.
+A default of ``nothing'' means the empty definition.
+.LP
+.B Note:
+The symbol UseInstalled is not defined in any of the configuration
+files.
+It should be defined (by you, as nothing) in
+.I site.def
+if you want to use installed versions of
+.I imake ,
+.I makedepend
+and the configuration files.
+It can be defined in
+.I site.def ,
+but you must leave it undefined on the initial build,
+obviously, since the configuration programs
+and files will not have been installed yet.
+.NH
+Imake.tmpl
+.NH 2
+Global Constant Definitions
+.LP
+This section defines the two symbols YES and NO:
+.Ds
+.ta 1i 2i
+#define YES 1
+#define NO 0
+.De
+These are heavily used to define boolean symbols.
+.NH 2
+Header Blocks
+.LP
+Every header block in this section of
+.I Imake.tmpl
+defines two symbols:
+.LP
+.Sy MacroIncludeFile <generic.cf> general
+.Sy MacroFile generic.cf general
+.IP
+Both of these name the platform-specific file to be included by the
+template after the header block section.
+The defaults are deliberately rebarbative and are selected only if the
+correct header block for your system was not triggered.
+Otherwise these symbols will have values like
+.I platform .cf> <
+and
+.I platform .cf,
+where
+.I platform
+is ``ultrix'', ``sun'', ``hp'', ``apollo'', etc.
+.IP
+There are two symbols associated with this name because it is used two
+different ways.
+MacroIncludeFile is used by
+.I cpp
+to include the platform file.
+MacroFile is used to generate file names.
+.IP
+In addition to the above two symbols, header blocks may define one or more
+of the following symbols to indicate the software and/or hardware platform.
+.Ds .IP
+.ta 3i
+AIXArchitecture PS2Architecture
+ATTArchitecture PegasusArchitecture
+ApolloArchitecture RtArchitecture
+CrayArchitecture SGIArchitecture
+HPArchitecture SonyArchitecture
+IBMArchitecture StellarArchitecture
+M4330Architecture SunArchitecture
+MacIIArchitecture UltrixArchitecture
+MipsArchitecture VaxArchitecture
+.De .IP
+Some of these symbols may be defined in more than one header block.
+The platform file may also define other \fIxxx\fRArchitecture symbols
+.I sun.cf (
+does so, for instance, to allow SPARC- or i386-dependencies to be selected.)
+.NH
+System/Build Definitions
+.NH 2
+Preprocessor Symbols
+.LP
+Symbols are listed in order of their appearance in
+.I Imake.tmpl .
+The default value of some symbols is determined based
+on whether SystemV is YES or NO.
+For these symbols both defaults are listed, with the SystemV=YES case first.
+.LP
+.Sy SystemV varies boolean
+.IP
+SystemV indicates whether your system is System V based (YES) or not
+(NO).
+If not, that usually means BSD based.
+The default value of many other symbols depends on SystemV, so it is
+usually set explicitly early
+in the platform-specific file to make sure it's correct.
+.LP
+.Sy OSMajorVersion "0" general
+.Sy OSMinorVersion "0" general
+.IP
+These two symbols indicate the major and minor version numbers of the
+operating system.
+They are often used as control symbols in the platform files
+to select symbol values that vary depending on the OS version.
+For this reason, they are usually set in the platform file.
+.IP
+Example: if some feature of your OS didn't appear until version 5.7,
+you could test for that with:
+.Ds .IP
+/**/# these definitions would go in the platform file
+# ifndef OSMajorVersion
+# define OSMajorVersion 5
+# endif
+# ifndef OSMinorVersion
+# define OSMinorVersion 7
+# endif
+
+/**/# this test would go wherever you need to test for 5.7 and up
+# if OSMajorVersion >= 5 && OSMinorVersion >= 7
+ /**/# 5.7-and-up specific stuff here
+# endif
+.De
+.LP
+.Sy UnalignedReferencesAllowed "NO" boolean
+.IP
+Some processors can dereference pointers to arbitrary addresses.
+Others cannot\*-inability to dereference odd addresses is a typical problem
+for such processors.
+If your pointers must be specifically aligned (e.g., on word
+boundaries), define UnalignedReferencesAllowed as NO.
+The default reflects a conservative approach.
+.LP
+.Sy ExecableScripts "NO/YES" boolean
+.IP
+Whether the kernel
+.I exec ()
+system call correctly executes scripts beginning with ``#!''.
+ExecableScripts determines the way the CppScriptTarget() rule macro is
+expanded and thus the way shell scripts are built.
+.IP
+Script prototypes begin with a line that says ``#!/bin/sh''.
+If ExecableScripts is NO, that line is stripped out and replaced with
+one that says ``:''.\**
+.FS
+I would say that a better way to do it might be to explicitly write
+a line into the script using the value of ${SHELL} if ExecableScripts
+is YES and ``:'' otherwise.
+This would allow the value of SHELL to propagate into scripts were it
+defined as something other than
+.I /bin/sh .
+.FE
+.LP
+.Sy BourneShell "/bin/sh" general
+.IP
+Path name of Bourne shell.
+This is used to set the value of SHELL, and in construction of some
+commands that run shell scripts.
+.LP
+.Sy ConstructMFLAGS "YES/NO" boolean
+.IP
+Whether to construct MFLAGS
+.I make
+variable from MAKEFLAGS.
+This is used (I think) for compatibility with versions of
+.I make
+that use MFLAGS instead of MAKEFLAGS.
+.LP
+.Sy HasLargeTmp "NO" boolean
+.IP
+Whether the file system on which
+.I /tmp
+resides has lots of free space.
+The meaning of ``lots'' is roughly 1MB, although that may need to be revised
+upward for future releases.
+This symbol determines the default value of ArCmd.
+.LP
+.Sy HasSockets "NO/YES" boolean
+.IP
+Whether the system has BSD socket support.
+.LP
+.Sy HasVFork "NO/YES" boolean
+.IP
+Whether the
+.I vfork ()
+system call is supported.
+Presumably this causes
+.I fork()
+to be used instead of
+.I vfork()
+if HaveVFork is NO.
+.LP
+.Sy HasPutenv "NO" boolean
+.IP
+Whether the
+.I putenv ()
+C library call is supported.
+.LP
+.Sy HasVoidSignalReturn "YES/NO" boolean
+.IP
+Whether the
+.I signal ()
+C library call returns
+.I void *
+(YES)
+or
+.I int *
+(NO).
+The default is YES for System V platforms, but
+if you have a BSD platform, you should not assume NO.
+Some BSD-based systems (e.g., Ultrix and Sun) have changed from
+.I int *
+to
+.I void *
+in new OS releases.
+Some machines try to support both sets of semantics.
+.LP
+.Sy HasBsearch "YES/NO" boolean
+.IP
+Whether the
+.I bsearch ()
+C library call is supported.
+.LP
+.Sy HasSaberC "NO" boolean
+.IP
+Whether the system has the Saber C development environment.
+The default value of this symbol will usually be overridden in the
+platform file.
+.B Warning:
+some of the platform files define HasSaberC as YES, so be sure to
+check this and change it if necessary.
+.LP
+.Sy HasFortran "NO" boolean
+.IP
+Whether the system has a FORTRAN compiler.
+Needed for GKS support.
+.LP
+.Sy HasNdbm "NO" boolean
+.IP
+Whether the system has the NDBM database manager (supercedes DBM).
+.LP
+.Sy HasDESLibrary "NO" boolean
+.IP
+Whether the system has a DES (digital encryption standard) library.
+.LP
+.Sy NeedFunctionPrototypes "NO" boolean
+.Sy NeedWidePrototypes "YES" boolean
+.IP
+These are used to support use of function prototypes.
+Apparently they are not well-liked judging from the deprecatory comments
+in the latter part of
+.I Imake.tmpl .
+.LP
+.Sy HasSunOSSharedLibraries "NO" boolean
+.IP
+Whether SunOS shared libraries are supported.
+.LP
+.Sy SharedCodeDef "varies" general
+.IP
+Flags to compile sharable library code.
+.LP
+.Sy SharedLibraryDef "varies" general
+.IP
+Flags to turn on use of shared libraries.
+.LP
+.Sy HasSharedLibraries "varies" boolean
+.IP
+Whether shared libraries are supported.
+.B Note:
+This symbol is defined
+.I inside
+the (convoluted) definition of SharedLibraryDef.
+.LP
+.Sy StripInstalledPrograms "NO" boolean
+.IP
+If YES, strip symbol table from installed programs, otherwise leave intact.
+Setting to YES can save lots of disk space on some machines, but
+leaving it as NO can help during debugging.
+This symbol affects use of InstPgmFlags.
+.LP
+.Sy DestDir nothing general
+.IP
+Prefix to prepend to installation directory pathnames.
+Normally this is left empty.
+If you want to install under an alternate root, the X folks recommend that
+you compile with the default value, then install with
+.Ds .IP
+make install DESTDIR=/alt/root
+.De .LP
+.Sy UsrLibDir "$(DESTDIR)/usr/lib" general
+.IP
+Directory under which to install system libraries (e.g.,
+.I lint
+libraries; see description of LintlibDir under
+.I Project.tmpl ).
+This is also used as the basis for the default value of LibDir (in
+.i Project.tmpl ), which is used for installation of libraries for
+.I xdm ,
+.I awm ,
+.I twm ...
+.LP
+.Sy IncRoot "$(DESTDIR)/usr/include" general
+.IP
+Path to root of system header file hierarchy.
+X11 header files are installed under this.
+(A default for this symbol is also included in
+.I Project.tmpl ;
+you can ignore it because the definition in
+.I Imake.tmpl
+occurs first and will override it.)
+.LP
+.Sy UNCOMPRESSPATH "/usr/ucb/uncompress" general
+.IP
+Command to run the
+.I uncompress
+program.
+I think this is used to uncompress compressed font files.
+If you override this symbol, the definition should probably be a full
+path name.
+.LP
+.Sy OptimizedCDebugFlags "\-O" general
+.IP
+C compiler flags to turn on optimization.
+.LP
+.Sy DebuggableCDebugFlags "\-g" general
+.IP
+C compiler flags to turn on debugging information.
+.LP
+.Sy NoOpCDebugFlags nothing general
+.IP
+C compiler flags to not turn on optimization or debugging.
+.LP
+.Sy DefaultCDebugFlags "OptimizedCDebugFlags" general
+.IP
+C compiler flags to turn on optimization for programs.
+.LP
+.Sy LibraryCDebugFlags "OptimizedCDebugFlags" general
+.IP
+C compiler flags to turn on optimization for libraries.
+.LP
+.Sy DefaultCCOptions nothing general
+.IP
+Special C compiler flags (other than \-I's and \-D's?
+See StandardDefines, StandardCppDefines).
+Useful, e.g., for turning on floating point options.
+.LP
+.Sy LibraryCCOptions "DefaultCCOptions" general
+.IP
+Special C compiler flags for compiling libraries.
+.LP
+.Sy ServerCCOptions "DefaultCCOptions" general
+.IP
+Special C compiler flags for compiling the server.
+(This is X-specific and should be in
+.I Project.tmpl ,
+perhaps?)
+.LP
+.Sy PexCDebugFlags "\-g" general
+.IP
+C compiler flags to turn on debugging information for PEX.
+(This is X-specific and should be in
+.I Project.tmpl ,
+perhaps?)
+.LP
+.Sy InstPgmFlags "\-s" general
+.IP
+Flags for installing programs.
+The default strips symbol tables.
+This symbol is used in conjunction with StripInstalledPrograms to set
+the
+.I make
+variable INSTPGMFLAGS.
+Note that INSTPGMFLAGS applies to installs of
+binary programs and also shell
+scripts; some systems give a warning when you try to strip a script
+because they have no symbol table (such warnings can be ignored).
+.LP
+.Sy InstBinFlags "\-m 0755" general
+.IP
+Flags for setting the mode of installed executable files.
+.LP
+.Sy InstUidFlags "\-m 4755" general
+.IP
+Flags for setting the mode of installed set-user-id files (e.g.,
+.I xterm
+needs to
+.I chown
+pty's).
+.LP
+.Sy InstLibFlags "\-m 0664" general
+.IP
+Flags for setting the mode of installed libraries.
+.LP
+.Sy InstIncFlags "\-m 0444" general
+.IP
+Flags for setting the mode of installed header files.
+.LP
+.Sy InstManFlags "\-m 0444" general
+.IP
+Flags for setting the mode of installed manual pages.
+.LP
+.Sy InstDatFlags "\-m 0444" general
+.IP
+Flags for setting the mode of installed data (non-executable) files.
+.LP
+.Sy InstKmemFlags "InstUidFlags" general
+.IP
+Flags for installing programs that need to read
+.I /dev/kmem ,
+e.g.,
+.I xload .
+The default makes such programs setuid, which is overkill, since
+typically all that's needed is setgid to the group having access to
+.I /dev/kmem .
+InstKmemFlags
+is a good symbol to define in
+.I site.def .
+Be sure to include the correct group, e.g., ``\-g kmem \-m 2755''.
+The group is not set in the default value of this symbol because
+it's difficult to determine a good default group.
+.LP
+.Sy ArCmd "varies" general
+.IP
+Command to create archive files.
+If HasLargeTmp is YES,
+.I /tmp
+is used for temp file space, otherwise the current directory is used.
+.LP
+.Sy BootstrapCFlags nothing general
+.IP
+Defines needed to get
+.I ccimake
+compiled and by
+.I imake
+to get
+.I cpp
+to select the correct header block in
+.I Imake.tmpl .
+.LP
+.Sy CcCmd "cc" general
+.IP
+Command to run the C compiler.
+.LP
+.Sy HasGcc "NO" boolean
+.IP
+Whether GNU CC,
+.I gcc ,
+is available.
+.LP
+.Sy ServerCcCmd "CcCmd" general
+.IP
+Command to run the C compiler to compile the server.
+(This is X-specific and should be in
+.I Project.tmpl ,
+perhaps?)
+.LP
+.Sy LibraryCcCmd "CcCmd" general
+.IP
+Command to run the C compiler to compile libraries.
+.LP
+.Sy FortranCmd "f77" general
+.IP
+Command to run the FORTRAN compiler.
+.LP
+.Sy FortranFlags nothing general
+.IP
+General flags for FORTRAN compiler.
+.LP
+.Sy FortranDebugFlags nothing general
+.IP
+Flags for FORTRAN compiler to turn on debugging information.
+.LP
+.Sy AsCmd "as" general
+.IP
+Command to run the assembler.
+.LP
+.Sy CompressCmd "compress" general
+.IP
+Command to run
+.I compress .
+.LP
+.Sy CppCmd "/lib/cpp" general
+.IP
+Command to run C preprocessor.
+.LP
+.Sy PreProcessCmd "CcCmd \-E" general
+.IP
+Command to preprocess input.
+This is used by the script version of
+.I makedepend .
+.LP
+.Sy InstallCmd "$(SCRIPTSRC)/bsdinst.sh / install" general
+.IP
+Command to install files.
+It should be compatible with the BSD version of
+.I install .
+.LP
+.Sy LdCmd "ld" general
+.IP
+Command to run the loader.
+.LP
+.Sy LintCmd "lint" general
+.IP
+Command to run
+.I lint .
+.LP
+.Sy LintLibFlag "\-o/\-C" general
+.IP
+Flags to build
+.I lint
+libraries.
+.LP
+.Sy LintOpts "\-ax/\-axz" general
+.IP
+Flags to tell
+.I lint
+how picky to be.
+.LP
+.Sy CpCmd "cp" general
+.IP
+Command to copy files.
+.LP
+.Sy LnCmd "ln/ln \-s" general
+.IP
+Command to link files.
+Symbolic links are used if available (not System V).
+.LP
+.Sy MakeCmd "make" general
+.IP
+Command to run
+.I make .
+.LP
+.Sy MvCmd "mv" general
+.IP
+Command to rename files.
+.LP
+.Sy RanlibCmd "/bin/true / ranlib" general
+.IP
+Command to run
+.I ranlib .
+On System V platforms this command is missing.
+.I /bin/true ,
+a nop, is used instead.
+.I /bin/true "" (
+always succeeds, which is important for
+.I make .)
+.LP
+.Sy RanlibInstFlags nothing general
+.IP
+Flags to pass to
+.I ranlib
+when run on libraries that have already been installed.
+``\-t'' is a good option here, if you have it.
+.LP
+.Sy RmCmd "rm \-f" general
+.IP
+Command to remove files.
+.LP
+.Sy StandardCppDefines "\-DSYSV/nothing" general
+.IP
+\-D's for C preprocessor.
+.LP
+.Sy StandardIncludes nothing general
+.IP
+\-I's for C compiler.
+.LP
+.Sy StandardDefines "\-DSYSV/nothing" general
+.IP
+\-D's for C compiler.
+.LP
+.Sy NdbmDefines "varies" general
+.IP
+Flags to turn on NDBM support.
+Affected by HasNdbm.
+.LP
+.Sy ExtraLibraries nothing general
+.IP
+Extra libraries needed to get programs to compile.
+.LP
+.Sy ExtraLoadFlags nothing general
+.IP
+Extra flags needed to get loader to work.
+.LP
+.Sy LdCombineFlags "\-X \-r" general
+.IP
+Flags for incremental loader support.
+.LP
+.Sy CompatibilityFlags nothing general
+.IP
+Flags to turn on R3 backward compatibility support.
+.LP
+.Sy TagsCmd "ctags" general
+.IP
+Command to generate tags files.
+.LP
+.Sy LoaderLibPrefix nothing general
+.IP
+Flags to specify before libraries (see
+.I cray.cf ).
+.LP
+.Sy TOPDIR "." general
+.Sy CURDIR "." general
+.IP
+Top of source tree, and current directory.
+The
+.I make
+variables associated with these (TOP, CURRENT_DIR)
+are overridden by recursive
+.I make
+rules.
+The defaults are correct for the top of the source tree.
+TOP and CURRENT_DIR are reset for each
+.I Makefile
+during ``make Makefiles''.
+TOP is the path to the top of the source tree, from the current
+directory.
+CURRENT_DIR is the path to the current directory from the top of the
+source tree.
+.LP
+.Sy FilesToClean "*.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut" general
+.IP
+List of files to be removed by ``make clean''.
+Note that ``*~'' is in this list, and see discussion of the
+RemoveProgramTarget() rule.
+If you are in the habit of using ``cp x x~'' to make a backup copy of
+files you modify, ``make clean'' will remove those copies, which may
+not be what you want.
+.NH 2
+Make Variables
+.LP
+Many of the
+.I make
+variables in
+.I Imake.tmpl
+are simply set to the preprocessor variable of the same name (e.g.,
+INSTBINFLAGS = InstBinFlags).
+.LP
+Most
+.I make
+variables referring to commands are set to the preprocessor symbol having
+the same name and a suffix ``Cmd''.
+For instance, CC and MAKE are set to CcCmd and MakeCmd, respectively.
+.LP
+The rest of the variables are set to
+preprocessor symbols with names that differ a bit from the variable
+name (e.g., SHELL = BourneShell), or are defined in terms of other
+.I make
+variables (e.g., MFLAGS = -$(MAKEFLAGS)), or a combination of
+preprocessor symbols and
+.I make
+variables (e.g., RM_CMD = $(RM) FilesToClean).
+.NH
+platform.cf
+.LP
+Symbols which definitely should be set here are
+BuildServer (and X\fIxxx\fRServer if BuildServer is YES),
+OSName, OSMajorVersion, and OSMinorVersion.
+Some other symbols you should think about setting are
+CCompilerMajorVersion,
+CCompilerMinorVersion,
+BootstrapCFlags,
+SystemV,
+UnalignedReferencesAllowed,
+SetTtyGroup,
+ExecableScripts,
+and
+ConstructMFLAGS.
+.NH
+site.def
+.LP
+You should read through the
+.I site.def
+file and follow the comments there which tell whether you should
+supply
+override definitions for a number of symbols.
+This is the place to indicate whether you have a large temp area
+(HasLargeTmp), whether you have GNU
+.I cc
+(HasGcc), whether you want to compile in R3 backward compatibility
+(CompatibilityFlags), etc.
+It's also a good place to set symbols such as InstKmemFlags and
+BuildExamples.
+.NH
+Project.tmpl
+.NH 2
+Preprocessor Symbols
+.LP
+Symbols are listed in order of their appearance in
+.I Project.tmpl .
+.LP
+.Sy ProjectX 4 general
+.IP
+X11 Release number.
+The
+.I README
+says this is a boolean, which is incorrect.
+.LP
+.Sy BuildServer YES boolean
+.IP
+Whether to build the server.
+This should be defined as NO in
+.I site.def
+on client-only systems.
+On platforms which have no server implementation, the value of
+BuildServer may already be set to NO in the platform file.
+.LP
+.Sy BuildExamples YES boolean
+.IP
+Whether to build the example programs.
+It will speed up your builds to override this as NO, and less disk
+space will be used.
+.IP
+It is probably possible to build selected examples only.
+Define BuildExamples as YES, then build all the Makefiles from the
+source root.
+Then build the ``clean'' and ``depend'' targets.
+Define BuildExamples as NO and rebuild the Makefiles.
+The examples directories should be left alone since BuildExamples
+is NO, but you can then go into an example directory and build the
+program since its
+.I Makefile
+should be correct.
+(This is all conjecture.)
+.LP
+.Sy BuildXawBC NO boolean
+.IP
+Whether to build backward-compatible X Athena Widgets (I think).
+.LP
+.Sy InstallXinitConfig NO boolean
+.IP
+Whether to install sample
+.I xinit
+configuration files.
+.LP
+.Sy InstallXdmConfig NO boolean
+.IP
+Whether to install sample
+.I xdm
+configuration files.
+.LP
+.Sy InstallAppDefFiles YES boolean
+.IP
+Whether to install application defaults
+files.
+.LP
+.Sy InstallOldHeaderFiles NO boolean
+.IP
+Whether to install R3 header files.
+.LP
+.Sy DebugLibX NO boolean
+.IP
+Whether to build debugging into the X library.
+.LP
+.Sy DebugLibXArchive NO boolean
+.IP
+Whether to build debugging into the archive file version of the X library.
+.LP
+.Sy ProfileLibX NO boolean
+.IP
+Whether to build profiling into the X library.
+.LP
+.Sy ProfileLibXArchive NO boolean
+.IP
+Whether to build profiling into the archive file version of the X library.
+.LP
+.Sy DebugOldLibX NO boolean
+.Sy ProfileOldLibX NO boolean
+.Sy DebugLibXt NO boolean
+.Sy ProfileLibXt NO boolean
+.Sy DebugLibXaw NO boolean
+.Sy ProfileLibXaw NO boolean
+.Sy DebugLibXext NO boolean
+.Sy ProfileLibXext NO boolean
+.Sy DebugLibXmu NO boolean
+.Sy ProfileLibXmu NO boolean
+.IP
+Whether to build debugging and/or profiling into the old X library, X
+Toolkit library, X Athena Widget library, X Extension library or the
+X mu library.
+.LP
+.Sy NeedBerklibInXlib NO boolean
+.IP
+Whether BSD emulation is needed in Xlib.
+If YES, then BandAidLibrary is set to YES, some other related symbols
+are defined, and the BandAidLibraryMake() rule macro is defined.
+.LP
+.Sy ManDirectoryRoot /usr/man general
+.IP
+Path to the top of the manual page hierarchy relative to the default root
+directory.
+See also ManPath.
+.LP
+.Sy ManSuffix n general
+.IP
+Suffix for program manual pages.
+See ManSourcePath, ManDir.
+.LP
+.Sy LibManSuffix 3 general
+.IP
+Suffix for library manual pages.
+See ManSourcePath, LibmanDir.
+.LP
+.br
+.ta 6iR
+\fBUNCOMPRESSFILT\fR general
+.br
+\0\0default: \-DUNCOMPRESSFILT=\e"UNCOMPRESSPATH\e"
+.IP
+\-D's to run
+.I uncompress .
+.LP
+.br
+.ta 6iR
+\fBBDFTOSNFFILT\fR (default: general
+.br
+\0\0default: \-DBDFTOSNFFILT=\e"$(BINDIR)/bdftosnf\e"
+.IP
+\-D's to run
+.I bdftosnf
+to convert fonts from binary distribution format to server natural
+format.
+.LP
+.br
+.ta 6iR
+\fBSHELLPATH\fR general
+.br
+\0\0default: \-DSHELLPATH=\e"/bin/sh\e"
+.IP
+\-D's for command to run the shell.
+.LP
+.br
+.ta 6iR
+\fBZBDFTOSNFFILT\fR general
+.br
+\0\0default: \-DZBDFTOSNFFILT=\e"UNCOMPRESSPATH" | $(BINDIR)/bdftosnf $(FONTCFLAGS)\e""
+.IP
+\-D's to run
+.I uncompress
+and
+.I bdftosnf
+to convert compressed binary distribution format font files to server natural
+format.
+.LP
+.Sy FontFilters "UNCOMPRESSFILT BDFTOSNFFILT SHELLPATH ZBDFTOSNFFILT" general
+.IP
+\-D's for font conversion filters.
+.LP
+.Sy PrimaryScreenResolution 72 general
+.IP
+Resolution of default server screen, in dots per inch (dpi).
+This number applies both to horizontal and to vertical resolution; X
+assumes square pixels.
+.LP
+.Sy DefaultFontPath varies general
+.IP
+Path to font directory.
+If not set somewhere else, a default is guessed, based
+on PrimaryScreenResolution, to select between 75 dpi and 100 dpi fonts.
+.LP
+.Sy DefaultRGBDatabase $(LIBDIR)/rgb general
+.IP
+Path to RGB color database.
+.LP
+.Sy FontCompilerFlags \-t general
+.IP
+Flags for
+.I bdftosnf .
+.LP
+.Sy ConnectionFlags "\-DTCPCONN \-DUNIXCONN" general
+.IP
+What kinds of connections the server will accept.
+Common values are \-DTCPCONN, \-DUNIXCONN, \-DSTREAMSCONN.
+More than one can be specified.
+If the server is built, at least one must be specified.
+.LP
+.Sy FontDefines "\-DFONT_SNF \-DFONT_BDF \-DCOMPRESSED_FONTS" general
+.IP
+\-D's for font options.
+.LP
+.Sy ExtensionDefines nothing general
+.IP
+\-D's for server extensions.
+Default is nothing, for ``no extensions''.
+This is typically overridden in the platform file for servers that
+know about particular extensions, or in
+.I site.def .
+.LP
+.Sy ServerCDebugFlags OptimizedCDebugFlags general
+.IP
+C compiler flags to turn on optimization/debugging in server.
+.LP
+.Sy LibraryDefines StandardDefines general
+.IP
+\-D's for compiling libraries.
+.LP
+.Sy ServerDefines "StandardDefines ExtensionDefines" general
+.IP
+\-D's for compiling the server.
+.LP
+.Sy CppSourcesPresent NO boolean
+.IP
+Whether you have BSD
+.I cpp
+sources.
+.LP
+.Sy CppSources /usr/src/lib/cpp general
+.IP
+Path to BSD
+.I cpp
+sources.
+Not used if CppSourcesPresent is NO.
+.LP
+.Sy BinDir $(DESTDIR)/usr/bin/X11 general
+.IP
+Where to install programs.
+.LP
+.Sy IncRoot $(DESTDIR)/usr/include general
+.IP
+IGNORE this symbol in
+.I Project.tmpl ;
+it's redundant.
+See its definition in the system/build section of
+.I Imake.tmpl .
+.LP
+.Sy BuildIncRoot $(TOP) general
+.IP
+Relative path to (parent of) top of header file tree within source tree.
+.LP
+.Sy BuildIncTop .. general
+.IP
+Top of header file tree within source tree, relative to $(TOP)/X11.
+.LP
+.Sy LibDir $(USRLIBDIR)/X11 general
+.IP
+X library installation directory (other directories are installed under
+this, e.g., FontDir, XinitDir).
+.LP
+.Sy ConfigDir $(LIBDIR)/config general
+.IP
+Where to install configuration files.
+.LP
+.Sy LintlibDir $(USRLIBDIR)/lint general
+.IP
+Where to install lint libraries.
+Note that the default uses USRLIBDIR, not LIBDIR.
+Also note that the name of this symbol is LintlibDir, not LintLibDir.
+.LP
+.Sy FontDir $(LIBDIR)/fonts general
+.IP
+Where to install fonts.
+.LP
+.Sy AdmDir $(DESTDIR)/usr/adm general
+.IP
+Where system log files are found.
+.LP
+.Sy XinitDir $(LIBDIR)/xinit general
+.IP
+Where to install
+.I xinit
+files.
+.LP
+.Sy XdmDir $(LIBDIR)/xdm general
+.IP
+Where to install
+.I xdm
+files.
+.LP
+.Sy XdmConfigurationSubdirectory config/default general
+.IP
+Default
+.I xdm
+configuration directory.
+.LP
+.Sy AwmDir $(LIBDIR)/awm general
+.IP
+Where to install
+.I awm
+files.
+.LP
+.Sy TwmDir $(LIBDIR)/twm general
+.IP
+Where to install
+.I twm
+files.
+.LP
+.Sy GwmDir $(LIBDIR)/gwm general
+.IP
+Where to install
+.I gwm
+files.
+.LP
+.Sy ManPath $(DESTDIR)ManDirectoryRoot general
+.IP
+Full path to top of manual page hierarchy.
+.LP
+.Sy ManSourcePath $(MANPATH)/man general
+.IP
+Path to top of manual page hierarchy, plus common suffix of manual page
+directories there.
+.LP
+.Sy ManDir $(MANSOURCEPATH)ManSuffix general
+.IP
+Where to install program manual pages.
+.LP
+.Sy LibmanDir $(MANSOURCEPATH)LibManSuffix general
+.IP
+Where to install library manual pages.
+.LP
+.Sy XAppLoadDir $(LIBDIR)/app-defaults general
+.IP
+Where to install application defaults files.
+.LP
+.Sy OsNameDefines nothing general
+.IP
+I don't know what this is used for.
+It's referenced in
+.I lib/Xdmcp/Imakefile
+and
+.I lib/Xmu/Imakefile .
+.LP
+.Sy DefaultUserPath :/bin:/usr/bin:$(BINDIR):/usr/ucb general
+.IP
+Default
+.I xdm
+user PATH environment variable.
+.LP
+.Sy DefaultSystemPath /etc:/bin:/usr/bin:$(BINDIR):/usr/ucb general
+.IP
+Default
+.I xdm
+system PATH environment variable.
+.LP
+.Sy DefaultSystemShell BourneShell general
+.IP
+Default shell.
+.LP
+.Sy UseCCMakeDepend NO boolean
+.IP
+Whether to use the slow shell script version of
+.I makedepend
+(uses
+.I "cc \-E" ).
+It's best to use the compiled version if it works on your system.
+If the compiled version does not work as supplied with the distribution,
+it's probably
+worth a little effort to see if you can get it to work
+(particularly if you can't get the shell script version to work,
+either, which sometimes happens!).
+Possible problems:
+.I /usr/include
+is hardwired into the code; if you use
+.I gcc ,
+the library path is hardwired, too.
+.LP
+.Sy DependDir "varies" general
+.IP
+Path to
+.I makedepend
+sources.
+The default is dependent on UseCCMakeDepend.
+.LP
+.Sy ContribDir $(TOP)/../contrib general
+.IP
+Top of user-contributed source tree.
+.LP
+.Sy DependCmd $(DEPENDSRC)/makedepend general
+.IP
+Command to run
+.I makedepend.
+.LP
+.Sy RemoveTargetProgramByMoving NO boolean
+.IP
+This symbol affects expansion of the RemoveProgramTarget() rule.
+``Program'' in that rule's name is misleading; it can be used to remove any
+file, not just programs.
+.LP
+.Sy AllocateLocalDefines nothing general
+.IP
+\-D's to turn on
+.I alloca ().
+.LP
+.Sy SharedLibX varies boolean
+.Sy SharedOldLibX varies boolean
+.Sy SharedLibXt varies boolean
+.Sy SharedLibXaw varies boolean
+.Sy SharedLibXmu varies boolean
+.Sy SharedLibXext varies boolean
+.IP
+Whether to build shared versions of the X, old X, X Toolkit, X Athena
+Widget, X mu or X Extension libraries.
+The defaults are YES if HasSunOSSharedLibraries is YES, NO otherwise.
+.LP
+.Sy SharedXlibRev 4.2 general
+.Sy SharedOldXRev 4.0 general
+.Sy SharedXtRev 4.0 general
+.Sy SharedXawRev 4.0 general
+.Sy SharedXmuRev 4.0 general
+.Sy SharedXextRev 4.0 general
+.IP
+Version (revision) numbers of shared libraries.
+.LP
+.Sy HasInputExtension YES boolean
+.IP
+Whether there are any input extensions.
+.LP
+.Sy DoInstallExtensionsIntoXlib NO boolean
+.IP
+Whether the extension library should be merged into the X library.
+.LP
+.Sy BandAidLibraryNeeded YES boolean
+.Sy BandAidLibrarySources Berklib.c general
+.Sy BandAidLibraryObjects Berklib.o general
+.LP
+.LP
+.Sy BandAidLibraryMake() "take a look" general
+.LP
+.LP
+.Sy BandAidLibraryNeeded NO boolean
+.IP
+Whether a band-aid library is needed.
+This will be YES if NeedBerklibInXlib is YES.
+.IP
+I'm not sure what all the band-aid stuff is for.
+Perhaps for BSD socket emulation on System V platforms.
+.LP
+.Sy XawClientDepLibs "$(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)" general
+.IP
+Library dependencies for clients using the Athena Widgets (DEPLIBS).
+.LP
+.Sy XawClientLibs "$(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)" general
+.IP
+Library needed by clients using the Athena Widgets (LOCAL_LIBRARIES).
+.LP
+.Sy NeedDefaultDepLibs YES boolean
+.LP
+Affects the definitions of DEPLIBS, DEPLIBS1, DEPLIBS1, DEPLIBS3.
+.LP
+.NH 2
+Make Variables
+.LP
+Many of the
+.I make
+variables in
+.I Project.tmpl ,
+like those in
+.I Imake.tmpl ,
+bear a direct name relationship to proprocessor symbols with which they are
+associated.
+.LP
+Since much of the project source and installation directory layout
+is specified in this file, the number of variables defined in terms of other
+.I make
+variables (e.g., XMUSRC = $(LIBSRC)Xmu, DEMOSRC = $(TOP)/demos) is quite large.
+.NH
+Imake.rules
+.LP
+The X
+.I Imake.rules
+file rule definitions make heavy use of the following techniques:
+.IP (1)
+Use of the ``::'' construct is quite prevalent.
+In a
+.I make
+rule, if a target name is followed by ``:'', it's assumed to be the
+only rule for that target.
+If another rule with the same target is found, it's an error.
+If target names are followed by ``::'', there may be multiple rules
+for the targets.
+The X configuration files rely on this property of ``::'' in the
+following ways:
+.RS
+.IP (a)
+To make sure that certain targets are always present in the
+.I Makefile ,
+even if they are not otherwise generated from expansion of the macros
+in
+.I Imakefile .
+This way, subdirectory-traversing
+.I make
+operations can rely on those targets being present.
+For instance, many rules that build programs automatically generate a
+``clean'' target to remove the program.
+But if no such rule is used in the
+.I Imakefile ,
+there might be no ``clean'' target in the
+.I Makefile ,
+and ``make clean'' fails.
+That's not a disaster, but a ``make clean'' from the root of the
+source tree can result in a lot of apparent errors.
+To avoid this, an empty ``clean'' target is written to the
+.I Makefile ,
+using ``clean::''.
+If there is another ``clean'' target, the empty one doesn't hurt anything.
+If there isn't, the empty one prevents error messages.
+.IP
+Other default targets generated are ``tags'', ``install'',
+``install.man'', ``Makefile'', ``Makefiles'' and ``includes''.
+.IP (b)
+To allow commands like ``make all'' to trigger builds of an arbitrary
+number of targets.
+Without the ``::'' construct, the configuration process would need to
+be able to determine exactly which targets ``make all'' should
+generate, and produce a single ``all: target1 target2 ...'' rule.
+This would be a difficult task.
+Using ``::'', each program-building rule can generate its own ``all::
+target'' and they are all triggered.
+.RE
+.IP (2)
+Definitions are allowed to be overridden.
+All rules are defined using the following construct:
+.Ds .IP
+# ifndef \fIrulename\fR
+# define \fIrulename(arguments)\fR ...
+# endif
+.De .IP
+This should look familiar because it's the same construct used
+in the other configuration files to allow symbol values to be overridden.
+Since
+.I Imake.rules
+is the last configuration file read during a
+.I Makefile
+build,
+.I any
+of its rules may be redefined.
+Doing so can have far-reaching consequences, of course, so that's not
+something you want to do without thinking it through first.
+Nevertheless, it's sometimes useful, or even necessary.
+.IP
+The likely places for such overriding to occur are:
+.IP
+.I platform.cf \*-if
+a system does things in some strange way that's
+not easy to compensate for by defining the usual configuration symbols
+properly.
+For example, the file
+.I sgi.cf
+redefines a couple of rules, to account for non-standard file
+extensions.
+.IP
+.I site.def \*-if
+a rule just isn't right for your site, for some reason.
+.IP
+.I Imakefile \*-it's
+sometimes useful to override a rule in a particular directory, which
+can be done by defining the rule in that directory's
+.I Imakefile .
+The file
+.I config/Imakefile
+does this, for instance.
+Such redefinitions do
+.I not
+carry down through subdirectories.
+Also, since
+.I Imake.rules
+is seen before
+.I Imakefile ,
+you need to #undef the macro before redefining it.
+.IP (3)
+If a directory has subdirectories, and
+.I make
+operations in that directory should recurse down through the
+subdirectories, there should be a line that says
+.Ds .IP
+# define IHaveSubdirs
+.De .IP
+at the top of the
+.I Imakefile .
+This causes recursive ``install'', ``install.man'',
+``clean'', ``tags'', ``Makefile'' and ``includes'' target rules to be
+written into the
+.I Makefile
+(see end of
+.I Imake.tmpl ;
+the
+.I make
+variable SUBDIRS should set to the names of the subdirectories involved, as
+well).
+If you want CDEBUGFLAGS passed along to subdirectories, put another
+line at the top of the
+.I Imakefile
+that says
+.Ds .IP
+# define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
+.De .IP (4)
+As you scan through the rules, you'll notice that
+.I if
+constructs are not written like this:
+.Ds .IP
+if \fIcondition\fR then; \fIaction\fR; fi
+.De .IP
+Instead, they're written like this:
+.Ds .IP
+if \fIcondition\fR then; \fIaction\fR; else exit 0; fi
+.De .IP
+The reason for this is to deal with differing behaviors of
+.I if
+on various systems.
+On some systems, if you write ``if \fIcondition\fR; then \fIaction\fR; fi''
+and
+.I condition
+is false, the value of the statement is zero (on the grounds that the
+test executed to completion without error).
+On other systems, the value of the statement is non-zero (on the grounds
+that the test failed).
+The latter behavior is broken behavior; Ultrix in particular is guilty
+of it.
+.IP
+In the X rules,
+.I if
+tests are usually used to check whether some preliminary action needs to be
+performed before proceeding to the next step.
+Systems that return false when the
+.I if
+test fails cause
+.I make
+to exit early if the preliminary action does not need to be done, and
+the next step is\*-incorrectly\*-never executed.
+.IP
+In order to get around this, all
+.I if
+statements explicitly include an
+.I else
+clause to return zero when the condition fails, so that
+.I make
+will continue whether the condition is true or not.
+.NH 2
+Commonly Used Rules
+.LP
+Rules for building programs:
+.Ds
+NormalProgramTarget()
+SimpleProgramTarget()
+ComplexProgramTarget()
+ComplexProgramTarget_1()
+ComplexProgramTarget_2()
+ComplexProgramTarget_3()
+.De
+Rules for building shell scripts:
+.Ds
+CppScriptTarget()
+MakeScriptFromCpp()
+.De
+Rules for building libraries:
+.Ds
+NormalLibraryObjectRule()
+NormalLibraryTarget()
+.De
+Rules for installing files:
+.Ds
+InstallProgram()
+InstallLibrary()
+InstallManPage()
+InstallNonExec()
+InstallSubdirs()
+.De
+Rules for cleaning up:
+.Ds
+RemoveTargetProgram()
+CleanTarget()
+CleanSubdirs()
+.De
+Rules for generating Makefiles and dependencies:
+.Ds
+MakefileTarget()
+MakefileSubdirs()
+DependTarget()
+DependSubdirs()
+.De
+Many rules that compile programs also generate ``clean'' and ``all''
+targets.
+.NH 2
+Rule Descriptions
+.LP
+Each rule-generating macro in
+.I Imake.rules
+is described below, in the order in which they appear in that file.
+You should still read through the text of a rule before you use it
+to write your own
+.I Imakefile .
+.LP
+.B Disclaimer:
+I myself do not, for the most part, use the X rules, except in
+modified form for my own projects.
+There are likely to be a number of errors of understanding here.
+.LP
+.Ru SaberProgramTarget(program,srclist,objlist,locallibs,syslibs)
+.IP
+If HasSaberC is NO, this is a nop, otherwise it expands to a rule for
+``saber-\fIprogram\fR'' and causes Saber C to load source and object
+files for the program.
+Odd that ``#'' is in front of the rules, though.
+.LP
+.Ru RemoveTargetProgram(program)
+.IP
+Removes
+.I program
+(actually this symbol is misnamed because it can be used to remove any
+file, not just programs).
+If RemoveTargetProgramByMoving (from
+.I Project.tmpl )
+is YES,
+.I program
+is moved to
+.I program~
+instead.
+This allows you to keep the previous version around.
+Note that ``*~'' is in the list of files removed by CleanTarget(), so
+unless you override FilesToClean, ``make clean'' will remove these
+previous target versions.
+.LP
+.Ru BuildIncludes(srclist,dstsubdir,dstupdir)
+.IP
+Builds the header file directories in the source tree,
+and populates them.
+.LP
+.Ru NormalProgramTarget(program,objects,deplibs,locallibs,syslibs)
+.IP
+Builds one program.
+All object files and libraries are explicitly listed in the macro invocation.
+.I program
+is the program to be built.
+.I objects
+names the object files needed to build it from, e.g.,
+.I junk.o .
+.I deplibs
+names the libraries that must exist before linking is done.
+.I locallibs
+names the libraries in the source tree that should be linked in.
+.I syslibs
+names the system libraries (e.g., in
+.I /usr/lib )
+that should be linked in.
+These are named with
+.I \-l ,
+e.g.,
+.I \-lm .
+.IP
+A ``clean'' rule is also generated to remove the program (but not the
+objects).
+.IP
+Since this rule does not assume any default sources, you can use it
+several times in an
+.I Imakefile
+to build multiple programs.
+You should also set SRCS to the names of all the programs'
+source files and invoke DependTarget() in the
+.I Imakefile .
+Also invoke AllTarget(), giving it the names
+of all programs to build, and you'll need to include a rule to
+generate
+an ``install'' target for each program and an ``install.man'' target if
+there is a manual page.
+If you're a lint kind of person, you'll also want
+LintTarget().
+.LP
+.Ru SingleProgramTarget(program,objects,locallibs,syslibs)
+.IP
+This rule is deprecated.
+Don't use it.
+.LP
+.Ru SimpleProgramTarget(program)
+.IP
+This macro is used when the
+.I Imakefile
+is supposed to build a single program, and that program consists of a single
+source file.
+The macro sets SRCS to
+.I program.c ,
+OBJS to
+.I program.o
+and calls ComplexProgramTarget().
+The effect is to set up everything to generate rules to build the program,
+install it and its man page, clean the program, generate dependencies,
+and lint the program.
+A real whiz bang.
+See description of ComplexProgramTarget().
+.LP
+.Ru ComplexProgramTarget(program)
+.IP
+This macro is used in an
+.I Imakefile
+that builds a single program.
+Given the name of the program, rules are generated to build it, as well as
+generate ``all'', ``install'', ``install.man'', ``depend'' and ``lint''
+targets, and to remove the program.
+Several assumptions are made by this macro:
+.RS
+.IP (1)
+SRCS has been set to the list of source files (so the ``depend'' target works).
+.IP (2)
+OBJS has been set to the list of object files (so the program build works).
+.IP (3)
+The
+.I deplibs ,
+.I locallibs
+and
+.I syslibs
+arguments as used in NormalProgramTarget() are assumed to be DEPLIBS,
+LOCAL_LIBRARIES and LDLIBS.
+.RE
+.LP
+.Ru ComplexProgramTarget_1(program,locallib,syslib)
+.br
+.Ru ComplexProgramTarget_2(program,locallib,syslib)
+.br
+.Ru ComplexProgramTarget_3(program,locallib,syslib)
+.IP
+These rules are use in an
+.I Imakefile
+that builds 1, 2 or 3 programs.
+Actually, just 2 or 3 programs.
+If you were building a single program, you'd use ComplexProgramTarget().
+Each macro takes 3 arguments.
+.I program
+is the name of the program to build.
+.I locallib
+names libraries built in the source tree that should be linked in
+(e.g., XMULIB).
+.I syslib
+names system libraries to be linked in (e.g.,
+.I \-lm ).
+.IP
+The values of certain
+.I make
+variables are assumed to be set (by you).
+SRCS1, SRCS2 and SRCS3 name the sources for each program.
+(These are used to set SRCS so the ``depend'' target works.)
+OBJS1, OBJS2 and OBJS3 name the objects for each program.
+DEPLIBS1, DEPLIBS2 and DEPLIBS3 name the library dependencies for each program.
+PROGRAMS names the programs to be built.
+.IP
+If you're only building 2 programs, then SRCS3, OBJS3, etc., do not
+need to be set and will be assumed to have the empty value.
+PROGRAMS should be the names of 2 programs, not 3.
+.LP
+.Ru ServerTarget(server,subdirs,objects,libs,syslibs)
+.IP
+Generates rules to build a server.
+.I libs
+doubles as
+.I deplibs
+and
+.I locallibs
+as those are used in NormalProgramTarget().
+The directories named by
+.I subdirs
+are used as dependencies and must exist before the target can be built.
+.LP
+.Ru InstallLibrary(libname,dest)
+.IP
+Installs
+.I liblibname.a
+into
+.I dest/liblibname.a
+and runs the command named by RANLIB on it.
+The installation flags INSTLIBFLAGS are used.
+.LP
+.Ru MergeIntoInstalledLibrary(tolib,fromlib)
+.IP
+Merges
+.I fromlib
+into
+.I tolib
+using the
+.I mergelib
+script in the SCRIPTSRC directory.
+.LP
+.Ru InstallSharedLibrary(libname,rev,dest)
+.IP
+Installs
+.I liblibname.so.rev
+into
+.I dest/liblibname.so.rev ,
+using INSTLIBFLAGS.
+.LP
+.Ru InstallSharedLibraryData(libname,rev,dest)
+.IP
+Installs
+.I liblibname.sa.rev
+into
+.I dest/liblibname.sa.rev ,
+using INSTLIBFLAGS.
+.LP
+.Ru InstallLibraryAlias(libname,alias,dest)
+.IP
+In
+.I dest ,
+makes
+.I libalias.a
+an alias for
+.I liblibname.a
+by generating a link.
+.LP
+.Ru InstallLintLibrary(libname,dest)
+.IP
+Installs
+.I llib-llibname.ln
+into the
+.I dest
+directory using library installation flags INSTLIBFLAGS.
+.LP
+.Ru InstallManPageLong(file,destdir,dest)
+.IP
+Generate rule to install a manual page and rename it.
+The source manual page is
+.I file.man
+and is installed in
+.I destdir/dest. ManSuffix
+using installation flags INSTMANFLAGS.
+This is used to install pages whose names are long enough to tickle
+brain damage on systems that don't understand long file names.
+.LP
+.Ru InstallManPage(file,dest)
+.IP
+Generate rule to install the manual page
+.I file.man
+in
+.I dest/file. ManSuffix
+using installation flags INSTMANFLAGS.
+.LP
+.Ru InstallNonExec(file,dest)
+.IP
+Generate rules to install a non-executable file using installation
+flags INSTDATFLAGS.
+.LP
+.Ru InstallProgramWithFlags(program,dest,flags)
+.IP
+Generate rules to install an executable program using the specified
+flags.
+.LP
+.Ru InstallProgram(program,dest)
+.IP
+Generate rules to install an executable program.
+The comments in
+.I Imake.rules
+for this macro say something about INSTALLFLAGS, but that variable
+isn't actually used in the expansion of this macro, so I claim the
+flags used are
+simply INSTPGMFLAGS until someone demonstrates otherwise.
+.LP
+.Ru InstallScript(program,dest)
+.IP
+Generate rules to install
+.I program.script
+into
+.I dest/program
+using installation flags INSTPGMFLAGS.
+.IP
+This rule is obsolete.
+Use CppScriptTarget() and InstallProgram().
+.LP
+.Ru LinkFileList(step,list,dir,sub)
+.IP
+Generates rules for a target
+.I step
+to make links to all files in
+.I list
+in directory
+.I dir .
+The links are created in directory
+.I sub .
+Judging from the definition of this macro,
+.I sub
+is presumably so named because the rule changes directories into
+.I dir
+first and appears to expect
+.I sub
+to be a subdirectory.
+(Strictly speaking, that need not be true, since
+(i)
+.I sub
+could legally be an absolute path;
+(ii)
+.I sub
+could have a value such as ``../..''.
+But both those possibilities probably subvert the intent of the
+macro.)
+.LP
+.Ru InstallMultipleDestFlags(step,list,dest,flags)
+.IP
+Generates rules for a target
+.I step
+(e.g., ``install'') to install all the files in
+.I list
+into the directory
+.I dir
+using installation flags
+.I flags .
+The files in
+.I list
+are made the rule dependencies.
+.LP
+.Ru InstallMultipleDest(step,list,dest)
+.IP
+Like InstallMultipleDestFlags(), but assuming INSTALLFLAGS as the
+installation flags.
+Note: INSTALLFLAGS is not set by the X configuration files;
+you must give it a value in your
+.I Imakefile .
+.LP
+.Ru InstallMultiple(list,dest)
+.IP
+Like InstallMultipleDest(), but assuming ``install'' as the
+.I step
+argument.
+.LP
+.Ru InstallMultipleFlags(list,dest,flags)
+.IP
+Like InstallMultipleDestFlags(), but assuming ``install'' as the
+.I step
+argument.
+.LP
+.Ru InstallMultipleMan(list,dest)
+.IP
+Like InstallMultipleDest(), but assuming ``install.man'' as the
+.I step
+argument.
+.LP
+.Ru InstallAppDefaults(class)
+.IP
+If InstallAppDefFiles (from
+.I Project.tmpl )
+is #define'd, generates an ``install'' target to install
+.I class.ad
+into
+.I $(XAPPLOADDIR)/class
+using installation flags INSTAPPFLAGS.
+.IP
+INSTAPPFLAGS appears to be deprecated in
+.I Project.tmpl .
+.LP
+.Ru DependDependency()
+.IP
+If UseInstalled is not #define'd, this macro generates rules to check for the
+existence of
+.I makedepend
+in the source tree and build it if it's missing.
+This differs from the R3 rules, which failed if
+.I makedepend
+was missing.
+.LP
+.Ru DependTarget()
+.IP
+Generate rule to determine dependencies for source files named by SRCS.
+You have to define the value of SRCS yourself, unless you are using
+rules such as
+SimpleProgramTarget() or ComplexProgramTarget_{1,2,3}(), which do it
+for you.
+In the latter case, you need to define SRCS1, SRCS2 and SRCS3.
+.IP
+This macro uses DependDependency() to check for the existence of
+.I makedepend
+and build it if necessary.
+.LP
+.Ru CleanTarget()
+.IP
+Removes all the files named by FilesToClean and files whose names
+begin with ``#''.
+.IP
+To understand how this rule works, see how RM_CMD is defined in
+.I Imake.tmpl .
+.LP
+.Ru TagsTarget()
+.IP
+Generate rule to build a
+.I TAGS
+file from all
+.I *.c
+and
+.I *.h
+files.
+.LP
+.Ru ImakeDependency(target)
+.IP
+If UseInstalled is not #define'd, this macro generates rules to check for the
+existence of
+.I imake
+in the source tree and build it if it's missing.
+This differs from the R3 rules, which failed if
+.I imake
+was missing.
+.LP
+.Ru BuildMakefileTarget(imakefile,imakeflags)
+.IP
+Generate rules to build
+.I Makefile .
+The
+.I imakefile
+argument is superfluous (a bug?).
+Since it's ignored,
+.I Imakefile
+is assumed as the source from which to build
+.I Makefile .
+.I imakeflags
+is any special flags you want passed to the
+.I imake
+command.
+.IP
+This macro uses ImakeDependency() to check for the existence of
+.I imake
+and build it if necessary.
+.IP
+You don't use this rule explicitly unless you've #define'd
+IHaveSpecialMakefileTarget in your
+.I Imakefile .
+.LP
+.Ru MakefileTarget()
+.IP
+Generate rules to build a
+.I Makefile
+target from
+.I Imakefile ,
+so you can say ``make Makefile''.
+This target is automatically included in your
+.I Makefile
+when it is rebuilt by
+.I imake ,
+unless ``#define IHaveSpecialMakefileTarget'' is present
+in your
+.I Imakefile ,
+in which case you should include an invocation of
+BuildMakefileTarget() to build
+.I Makefile .
+.LP
+.Ru NormalLibraryObjectRule()
+.IP
+Generate rule to turn a
+.I .c
+file into a
+.I .o
+file.
+Include this macro (once) in your
+.I Imakefile
+if you're building a library from C source.
+.LP
+.Ru NormalFortranObjectRule()
+.IP
+Generate rule to turn a
+.I .f
+file into a
+.I .o
+file.
+Include this macro (once) in your
+.I Imakefile
+if you're building a library from FORTRAN source.
+(FORTRAN?
+Isn't that something used to build COBOL compilers?)
+.LP
+.Ru ProfiledLibraryObjectRule()
+.IP
+Like NormalLibraryObjectRule(), but in addition to building the normal
+target, a profiled target is built in the
+.I profiled
+subdirectory of the current directory.
+.I profiled
+is created if necessary.
+A ``clean'' target to remove profiled objects is also generated.
+.LP
+.Ru DebuggedLibraryObjectRule()
+.IP
+Like ProfiledLibraryObjectRule(), but instead of profiled targets in
+.I profiled ,
+debuggable targets are built in the
+.I debugger
+subdirectory.
+.LP
+.Ru DebuggedAndProfiledLibraryObjectRule()
+.IP
+A combination of ProfiledLibraryObjectRule() and DebuggedLibraryObjectRule().
+.LP
+.Ru SharedLibraryObjectRule()
+.IP
+Like ProfiledLibraryObjectRule(), but instead of profiled targets in
+.I profiled ,
+sharable targets are built in the
+.I shared
+subdirectory.
+.LP
+.Ru SharedAndDebuggedLibraryObjectRule()
+.IP
+A combination of SharedLibraryObjectRule() and DebuggedLibraryObjectRule().
+.LP
+.Ru SpecialSharedAndDebuggedObjectRule(objs,depends,options)
+.IP
+Like SharedAndDebuggedLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru SpecialSharedObjectRule(objs,depends,options)
+.IP
+Like SharedLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru SpecialObjectRule(objs,depends,options)
+.IP
+Like NormalLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru SpecialProfiledObjectRule(objs,depends,options)
+.IP
+Like ProfiledLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru SpecialDebuggedObjectRule(objs,depends,options)
+.IP
+Like DebuggedLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru SpecialDebuggedAndProfiledObjectRule(objs,depends,options)
+.IP
+Like DebuggedAndProfiledLibraryObjectRule(), but allows targets
+.I objs ), (
+dependencies and special compiler flags to be specified.
+.LP
+.Ru NormalLibraryTarget(libname,objlist)
+.IP
+Generate rules to create the library
+.I liblibname.a
+from the object files named by
+.I objlist .
+The library is RANLIB'd after being created.
+.LP
+.Ru NormalSharedLibraryTarget(libname,rev,solist)
+.IP
+Generate rules to create a shared library
+.I liblibname.so.rev .
+The library is created under a different name and then moved onto the
+target name to maximize availability of any existing version.
+.LP
+.Ru NormalSharedLibraryDataTarget(libname,rev,salist)
+.IP
+Like NormalSharedLibraryTarget(), but for shared data
+.I liblibname.sa.rev .
+The comments claim
+the library is created under a different name and then moved onto the
+target name as for NormalSharedLibraryTarget() but that doesn't appear
+to be true from the text of the macro.
+.LP
+.Ru NormalLibraryTarget2(libname,objlist1,objlist2)
+.IP
+Like NormalLibraryTarget(), but adds two lists of files to the
+library, in two steps.
+Used to create libraries with large numbers of files.
+.LP
+.Ru ProfiledLibraryTarget(libname,objlist)
+.IP
+Generate rules to create the library
+.I liblibname_p.a
+from the profiled objects in the
+.I profiled
+subdirectory.
+.LP
+.Ru DebuggedLibraryTarget(libname,objlist)
+.IP
+Generate rules to create the library
+.I liblibname_d.a
+from the debuggable objects in the
+.I debugger
+subdirectory.
+.LP
+.Ru AliasedLibraryTarget(libname,alias)
+.IP
+Generate rules to make
+.I libalias.a
+a link to
+.I liblibname.a .
+.LP
+.Ru NormalRelocatableTarget(objname,objlist)
+.IP
+Generate rules to produce a relocatable object file
+.I objname.o
+from the object files named in
+.I objlist .
+This is built using the loader LD, called with flags LDCOMBINEFLAGS.
+.LP
+.Ru ProfiledRelocatableTarget(objname,objlist)
+.IP
+Like NormalRelocatableTarget(), but builds
+.I objname_p.o
+and uses loader flag
+\-X instead of LDCOMBINEFLAGS, to produce a profiled relocatable
+object file.
+.LP
+.Ru DebuggedRelocatableTarget(objname,objlist)
+.IP
+Like NormalRelocatableTarget(), but builds
+.I objname_d.o
+and uses loader flag
+\-X instead of LDCOMBINEFLAGS, to produce a debuggable relocatable
+object file.
+.LP
+.Ru LintLibraryTarget(libname,srclist)
+.IP
+Generate rules for a ``lintlib'' target that builds
+.I llib-llibname.ln
+from the source files named by
+.I srclist .
+.LP
+.Ru NormalLintTarget(srclist)
+.IP
+Generate rules for a ``lint'' target that lints the source files named
+by
+.I srclist ,
+and for a ``lint1'' target that lints the file named by the
+.I make
+variable FILE (which you must set in
+.I Imakefile ).
+.LP
+.Ru LintTarget()
+.IP
+Generate rules to lint files named by SRCS.
+SRCS might be set by you in
+.I Imakefile ,
+or, if you invoke macros such as SimpleProgramTarget() or
+ComplexProgramTarget_{1,2,3}(), it will be done for you
+automatically.
+.LP
+.Ru LinkSourceFile(src,dir)
+.IP
+Generate rule to make a link to a file in another directory.
+The macro can be used to create links
+to non-source files, too, of course.
+.LP
+.Ru MakeSubincludesForBuild(step,dir,srclist)
+.IP
+Generate rules for target
+.I step
+to ... to ... uh, I don't know!
+.LP
+.Ru NamedTargetSubdirs(name,dirs,verb,flags,subname)
+.IP
+Generate rules for a target
+.I name
+(e.g., ``depend'', ``install'') that causes the target
+.I subname
+to be built in the subdirectories named by
+.I dirs .
+This is done by changing into each subdirectory in turn and invoking
+.I make
+for the
+.I subname
+target.
+.I flags
+is any extra flags that should be passed to those
+.I make
+processes.
+.I verb
+is the -ing form of
+.I name ,
+e.g., if
+.i name
+is ``make'', then
+.I verb
+is ``making''.
+This is used to echo an indication of what
+.I make
+is doing in each directory as it proceeds.
+.IP
+This macro is used by virtually all other macros that have names like
+XXXSubdirs().
+.LP
+.Ru NamedMakeSubdirs(name,dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a target
+.I name
+that causes the ``all'' target to be built in the
+subdirectories named by
+.I dirs .
+.IP
+If you want CDEBUGFLAGS passed to the
+.I make
+processes forked in each subdirectory, the
+.I Imakefile
+should have a line at the top that says:
+.RS
+.Ds
+# define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
+.De
+.RE
+.LP
+.Ru MakeSubdirs(dirs)
+.IP
+Equivalent to NamedMakeSubdirs(all,dirs).
+.LP
+.Ru DependSubdirs(dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a ``depend''
+target that causes the ``depend'' target to be built in the
+subdirectories named by
+.I dirs .
+.LP
+.Ru InstallSubdirs(dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a ``install''
+target that causes the ``install'' target to be built in the
+subdirectories named by
+.I dirs .
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru InstallManSubdirs(dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a ``install.man''
+target that causes the ``install.man'' target to be built in the
+subdirectories named by
+.I dirs .
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru IncludesSubdirs(dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a ``includes''
+target that causes the ``includes'' target to be built in the
+subdirectories named by
+.I dirs .
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru NamedCleanSubdirs(name,dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a target
+.I name
+that causes the ``clean'' target to be built in the
+subdirectories named by
+.I dirs .
+.LP
+.Ru CleanSubdirs(dirs)
+.IP
+Equivalent to NamedCleanSubdirs(clean,dirs).
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru NamedTagSubdirs(name,dirs)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a target
+.I name
+that causes the ``tags'' target to be built in the
+subdirectories named by
+.I dirs .
+.LP
+.Ru TagSubdirs(dirs)
+.IP
+Equivalent to NamedTagSubdirs(tags,dirs).
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru MakeLintSubdirs(dirs,target,subtarget)
+.IP
+Invokes NamedTargetSubdirs() to generate rules for a target
+.I target
+that causes the target
+.I subtarget
+to be built in the subdirectories named by
+.I dirs .
+.LP
+.Ru LintSubdirs(dirs)
+.IP
+Equivalent to MakeLintSubdirs(dirs,lint,lint).
+.IP
+This macro is
+.I not
+automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ;
+you need to do so yourself.
+.LP
+.Ru MakeLintLibSubdirs(dirs)
+.IP
+Equivalent to MakeLintSubdirs(dirs,lintlib,lintlib).
+.LP
+.Ru MakeMakeSubdirs(dirs,target)
+.IP
+Generate rules for a target
+.I target
+to generate a
+.I Makefile
+in the subdirectories named by
+.I dirs .
+.IP
+In R4, ``Makefiles'' rules handle values of ${TOP} that are either
+relative or absolute.
+The R3 rule only handled relative values.
+.LP
+.Ru MakeNsubdirMakefiles()
+.IP
+Generate a set of very very very ugly but quite wonderful rules for
+use by MakeMakeSubdirs().
+Automatically invoked by MakefileSubdirs(); you shouldn't need to do
+so yourself.
+.LP
+.Ru MakefileSubdirs(dirs)
+.IP
+Generate rules to build ``Makefiles''
+targets in the given subdirectories.
+.IP
+This macro is automatically invoked if IHaveSubdirs is #define'd in
+.I Imakefile ,
+in which case SUBDIRS should be set to the names of the subdirectories
+involved.
+.LP
+.Ru CppScriptTarget(dst,src,defs,deplist)
+.IP
+Generate rules to build a shell script
+.I dst
+from
+.I src .
+It figures out how to do this correctly for the current platform
+depending on the value of ExecableScripts.
+.I defs
+is any extra flags, such as \-D's, to pass through to the
+preprocessor.
+.I deplist
+names any targets that must exist before
+.I dst
+can be built.
+.LP
+.Ru MakeScriptFromCpp(name,defs)
+.IP
+Generate rule to build a script
+.I name
+from
+.I name.cpp .
+.I defs
+is as for CppScriptTarget().
+.LP
+.Ru MakeDirectories(step,dirs)
+.IP
+Generate rules for target
+.I step
+to create the directories named by
+.I dirs .
+This is often used to make sure that installation directories exist
+before trying to install files in them.
+(Not all verions of
+.I install
+create missing directories.)
+.LP
+.Ru MakeFonts()
+.IP
+Generate rules for ``fonts.dir'' target to build font database
+.I fonts.dir .
+The
+.I make
+variable OBJS must be set to the name of the files that should exist
+before the database is built.
+.LP
+.Ru InstallFonts(dest)
+.IP
+Generate rules to install the directory
+.I fonts.dir
+into
+.I dest
+using installation flags INSTDATFLAGS.
+.LP
+.Ru InstallFontAliases(dest)
+.IP
+Generate rules to install font alias database
+.I fonts.alias
+into
+.I dest
+using installation flags INSTDATFLAGS.
+.LP
+.Ru FontTarget(basename)
+.IP
+Generate rules to create a font file by converting
+.I basename.bdf
+to
+.I basename.snf .
+.LP
+.Ru CompressedFontTarget(basename)
+.IP
+Generate rules to create a compressed font file by converting
+.I basename.bdf
+(to
+.I basename.snf.Z ,
+I suppose).
+.LP
+.Ru AllTarget(depends)
+.IP
+Generate rule for an ``all'' target to build targets named by
+.I depends .
+.LP
+.NH
+Imakefile
+.LP
+If HasSaberC is #define'd, some special Saber-C rules are generated.
+.LP
+Some symbols that you may want to #define (as nothing) at the top of
+.I Imakefile
+are:
+.LP
+.Ru IHaveSpecialMakefileTarget
+.IP
+If not #define'd (the normal case), MakefileTarget() is automatically
+invoked.
+If #define'd, it's assumed that you want to explicitly invoke a
+.I Makefile -building
+macro yourself.
+.LP
+.Ru MakefileAdditions
+.IP
+If #define'd, MakefileAdditions() is automatically invoked.
+However, MakefileAdditions() appears not to be defined
+anywhere, and I have no idea what it is supposed to do.
+.LP
+.Ru IHaveSubdirs
+.IP
+If #define'd, you should set SUBDIRS to the names of the current
+directory's subdirectories, and subdirectory-traversing rules for
+generating ``Makefile'', ``install'', ``install.man'', ``clean'',
+``tags'' and ``includes'' targets will be automatically invoked.
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/config-X11R4-1.05.ms b/web/glasgow/lit2x-0.16/mkworld/docs/config-X11R4-1.05.ms
new file mode 100644
index 0000000000..8d7d974ab0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/config-X11R4-1.05.ms
@@ -0,0 +1,2456 @@
+.\" format with
+.\" tbl % | xroff -ms | lpr
+.\"
+.\" revision date - change whenever this file is edited
+.ds Rd 28 January 1991
+.\" document revision number - change each time document is released
+.ds Rn 1.05
+.\"
+.nr PO 1.2i \" page offset 1.2 inches
+.nr PD .7v \" inter-paragraph distance
+.\"
+.EH 'Imake in X11R4'- % -''
+.OH ''- % -'Imake in X11R4'
+.OF 'Revision date:\0\0\*(Rd'\s+1\*-DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.EF 'Revision date:\0\0\*(Rd'\s+1\*-DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.\"
+.\"
+.\" I - italic font (taken from -ms and changed)
+.de I
+.nr PQ \\n(.f
+.if t \&\\$3\\f2\\$1\\fP\&\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\c
+.if n .if \\n(.$>1 \&\\$2
+..
+.\" start block. LP gives a bit extra space. Can say .Ds .IP C, etc.
+.de Ds
+.if \\n(.$<1 .LP
+.if \\n(.$>=1 \\$1
+.if \\n(.$<2 .DS
+.if \\n(.$>=2 .DS \\$2 \\$3 \\$4 \\$5
+..
+.\" end block. If arg is given, it replaces the .LP (e.g., .De .IP).
+.de De
+.DE
+.if \\n(.$<1 .LP
+.if \\n(.$>=1 \\$1 \\$2 \\$3 \\$4 \\$5
+..
+.TL
+Using Imake to Configure
+.br
+the X Window System
+.br
+Version 11, Release 4
+.AU
+Paul DuBois
+dubois@primate.wisc.edu
+.AI
+Wisconsin Regional Primate Research Center
+Document revision:\0\0\*(Rn
+Revision date:\0\0\*(Rd
+.AB
+The X Window System\(dg
+.FS \(dg
+X Window System is a trademark of the Massachusetts Institute of Technology.
+.FE
+is a large software project that, despite its size,
+is remarkable in its portability.
+Much of this is due to the method employed to configure the X
+distribution for building and installation: use of a small number of
+tools and isolation of machine dependencies into a small number of
+files that can be easily maintained and modified.
+This document discusses one of those tools,
+.I imake ,
+and the design of the configuration files used in conjunction with it.
+.AE
+.NH
+Introduction
+.LP
+This document describes how
+.I imake
+configuration files are set up in the X Window System.
+It is assumed that you know something about what
+.I imake
+is supposed to be used for (in general),
+and that you're reading this to find out something
+about how that is accomplished in X (in particular).
+The description applies to X Version 11, release 4 configuration files, which
+are organized quite differently than those from previous releases.
+.LP
+Other documentation (from the X11R4 distribution) that you may find useful
+includes:
+.IP \(bu
+Section 2 of ``X Window System, Version 11 Release 4 Release Notes,''
+by Jim Fulton.
+.IP \(bu
+.I mit/doc/config/usenixws/paper.ms :
+``Configuration Management in the X Window System,'' also by Jim Fulton.
+.IP \(bu
+.I mit/config/README :
+``X Window System Imake Configuration Guide, Release 4.''
+.IP \(bu
+.I mit/config/imake.man :
+manual page for
+.I imake .
+.IP \(bu
+.I mit/util/makedepend/mkdepend.man :
+manual page for
+.I makedepend .
+.IP \(bu
+.I contrib/doc/imake/imake.tex :
+``An
+.I Imake
+Tutorial,'' by Mark Moraes.
+This was written between R3 and R4, but is worthwhile reading nonetheless.
+.LP
+You should also have access to the X configuration files (in
+.I mit/config ).
+These are not really documentation as such,
+but it is expected that you have them at hand, for comparison
+against the descriptions below.
+.LP
+.I imake
+is generally conceded to have a pretty steep learning curve.
+The
+.I README
+referred to above notes that
+.I imake
+``can be somewhat tricky to master,'' an observation attested to by
+many who use it.
+There seem to be three camps regarding
+.I imake ;
+those who think it's wonderful, those who think it's wretched, and those
+who suspect it might be useful (else why would it be used to configure
+a major publicly-available effort like X?) but are puzzled by it.
+The present document was written to fill in some of the gaps in the
+existing documentation, in order to try to swell the ranks of the first
+group by depleting the membership of the third.
+(Those who despise
+.I imake \*-members
+of the second group\*-have good reasons for doing so and the present
+effort is not likely to sway them.
+The author of
+.I imake
+is in this group.)
+.LP
+Where appropriate, the current X configuration files are compared to those
+from previous releases to show how limitations of earlier configuration
+architectures have been eased.
+There are also occasional comments to indicate how
+.I imake
+and the X configuration files might be adapted for use in contexts
+other than building X.
+.LP
+This document is independent of the efforts of the MIT X Consortium.
+There are no doubt errors lurking within, both of understanding and of fact;
+they are my own.
+Please send corrections, criticisms and comments to the address above.
+.LP
+The overall organization followed here is:
+.IP 1.
+Introduction.
+.IP 2.
+X configuration tool description\*-the programs you use.
+.IP 3.
+X configuration file description\*-what each file is used for, how each fits
+into the configuration process.
+.IP 4.
+How to build
+.I imake .
+.IP 5.
+How to build X.
+.IP 6.
+Configuration file bugs.
+.IP 7.
+How to write your own
+.I Imakefile .
+You can read this section without reading the rest of the paper,
+maybe.
+.IP 8.
+How to make mistakes writing an
+.I Imakefile .
+.IP Appendix
+Listing of the symbols used in each configuration file, and
+what they're used for.
+.NH
+The tools: imake, makedepend, xmkmf
+.LP
+.I imake
+is a configuration tool\*-the main tool used to configure X.
+It is not a replacement for the
+.I make
+program, but it does assume the availability of
+.I make
+as the tool used to direct project building and installation.
+What
+.I imake
+provides is an alternative to writing
+.I Makefiles
+by hand.
+The name means ``include-make''\*-\fIimake\fR
+uses the C preprocessor
+.I cpp ,
+taking advantage of its include-file and macro-processing
+facilities for the purpose of generating
+.I Makefiles
+suitable for
+.I make .
+.LP
+For each directory in the X distribution,
+.I imake
+reads a bunch of
+configuration files that go to a lot of trouble to compensate for and
+adjust to the individual characteristics of your system.
+These are combined with an
+.I Imakefile
+from the current directory and the whole mess is sent through
+.I cpp
+to build a
+.I Makefile
+there.
+The same configuration files are used to build every
+.I Makefile ;
+they are kept together in
+.I mit/config ,
+isolating machine dependencies in one location to ease development
+and maintenance.
+In contrast, the
+.I Imakefile
+is directory-specific (it specifies the targets to be built in that directory)
+and is machine-independent.
+.LP
+This means that when the distribution is built on a different machine,
+only the configuration files need be changed.
+The
+.I Imakefiles
+do not need to be.
+If X configuration were specified directly using
+.I Makefiles ,
+this would not be true.
+Because
+the configuration information in
+.I Makefiles
+is not portable, each one would have to be edited individually\*-bad
+enough for a single
+.I Makefile ,
+but an overwhelming prospect for a project the size of X.
+.LP
+The value of being able to localize machine-dependent configuration
+information into one place should not be underestimated, particularly
+as X becomes more sophisticated and the number of systems on which it
+runs increases.
+The number of
+.I make
+variables used to build X has increased from approximately 60
+in R1 to 100 in R3 to 150 in R4.
+.LP
+Another tool,
+.I makedepend ,
+is used to generate header file dependencies for C source files in
+each directory after the
+.I Makefile
+has been built.
+Dependencies of targets upon object files can be statically listed in the
+.I Imakefile ,
+but not those for header files.
+Different systems organize these differently so dependencies on them
+must be generated dynamically.
+.LP
+While X is being built,
+.I imake
+itself is located with the configuration files in
+.I mit/config .
+.I makedepend
+lives in
+.I util/makedepend
+if you use the compiled version (preferred),
+or in
+.I util/scripts
+if you use the shell script version (slower).
+.LP
+When X is installed, copies of
+.I imake ,
+.I makedepend ,
+and a related tool,
+.I xmkmf ,
+are placed in a public directory, and the configuration files are
+copied to
+.I /usr/lib/X11/config .
+.I xmkmf
+is used to bootstrap a
+.I Makefile
+from an
+.I Imakefile
+using the installed configuration files,\**
+.FS
+Normally a new
+.I Makefile
+is produced with ``make Makefile'', an operation that presumes you
+already have a properly configured
+.I Makefile
+containing the rules necessary to run
+.I imake .
+Hence the bootstrap problem.
+Obviously, if you know the proper incantation to utter, you can issue
+the appropriate
+.I imake
+command manually, but
+.I xmkmf
+eliminates the need.
+Besides, the only way you'd know which wand to wave is by having a
+reasonable understanding of
+.I imake
+in the first place\*-in which case you wouldn't be reading this!
+.FE
+and can be used to build
+programs from outside of the X source tree, such as you might write
+yourself or get from comp.sources.x on Usenet.
+.LP
+The X configuration files make very
+few assumptions about the capabilities of
+.I make
+itself.
+Although several enhanced versions of
+.I make
+provide special features or extensions, any
+.I Makefile
+that relies on universal availability of those features
+will fail on systems with less-capable versions of
+.I make .
+.I Makefiles
+produced by
+.I imake
+in X do not use any of these constructs, so they should work with
+even the lowest-common-denominator
+.I make
+program.
+.LP
+Since
+.I imake
+passes its input through
+.I cpp ,
+the configuration file writer can take advantage of several features
+not present in plain-vanilla
+.I make ,
+such as parameterized macros (using #define), file inclusion (using
+#include) and conditional testing (using #if, #ifdef, #ifndef).
+This ameliorates much of the sobering effect of having to assume that a dumb
+.I make
+is the only one available.
+.LP
+Use of
+.I cpp
+can produce problems, too, of course:
+.IP (1)
+How to specify, in configuration files, comments that should end up in the
+.I Makefile .
+.I make
+comments are introduced by a ``#'' character\*-unfortunately,
+.I cpp
+treats lines beginning with ``#'' as preprocessor directives.
+A comment of the form
+.Ds .IP
+# if your system doesn't have ranlib, use /bin/true
+.De .IP
+is considered a symbol test by
+.I cpp
+(it begins with ``if'') and is gobbled up, while a comment like
+.Ds .IP
+# The next rule is a workaround for a broken compiler
+.De .IP
+is not understood by
+.I cpp
+and generates a syntax error.
+To get around this, comments
+should be preceded by ``/**/#'' instead of just ``#''.
+.I cpp
+will strip off the ``/**/'' (the empty C comment)
+and won't treat the line as a directive (though it's
+still liable to symbol substitution).
+.IP
+The exception to this ``comment-commenting'' convention is in the
+.I Imakefile
+itself, where
+.I imake
+automatically adds ``/**/'' onto lines beginning with ``#'' that are not
+preprocessor directives.
+The reason for this is to insulate the end user of
+.I imake
+(who simply writes the
+.I Imakefile
+and not the underlying configuration files) from the need to be aware
+of, or abide by, the commenting convention.
+I would hazard a guess that many people are not aware of this
+exception, given the high incidence of
+.I Imakefiles
+containing ``/**/#''.
+.IP
+Comments that are not to be passed through to the
+.I Makefile
+can be written as normal C comments (text surrounded by ``/*'' and ``*/'')
+and will be deleted by
+.I cpp .
+.IP (2)
+Sometimes the values of
+.I cpp
+symbols are to be concatenated.
+The symbol names cannot be concatenated in the configuration files,
+because that results in a different symbol name, so they must be kept
+apart somehow.
+The empty C comment is useful here, too.
+For instance, if Prefix, LibName and Suffix are defined as
+.I lib ,
+.I mylib
+and
+.I .a ,
+respectively, then to obtain the concatentation value
+.I libmylib.a ,
+one writes Prefix/**/LibName/**/Suffix, not PrefixLibNameSuffix.
+.IP (3)
+The configuration files define several multiple-line macros that are
+intended to produce multiple lines of output.
+.I cpp
+joins multi-line macros into a single line, so some post-processing is
+necessary.
+.NH
+Configuration file architecture
+.LP
+To produce a
+.I Makefile
+from an
+.I Imakefile ,
+the following configuration files are used:
+.Ds
+.ta 1.5i
+Imake.tmpl master template
+\fIplatform\fR.cf platform-specific definitions (the filename varies)
+site.def site-specific definitions
+Project.tmpl X-specific default definitions
+Imake.rules \fIcpp\fR macros to generate \fImake\fR rules
+.De
+In general,
+if a port exists for your system, the only file that you should need to modify
+to build and install X is
+.I site.def .
+In some cases it may be necessary to modify the platform file.
+.I Imake.tmpl ,
+.I Project.tmpl
+and
+.I Imake.rules
+should be left alone.\**
+.FS
+It should be emphasized that ``should be left alone'' applies
+.I "only to building X itself" .
+If you are adapting the configuration files for use with another
+project, you will probably modify all of them somewhat.
+You may even find yourself in the position of having modified them to such
+an extent that they end up hacked to bits, incapable of configuring
+anything, with you left possessing only the faint hope that something useful
+will rise, Phoenix-like, from out of the remains.
+Be assured\*-it won't.
+But cheer up; start again and learn from your mistakes.
+.FE
+.LP
+If you are porting X to a new platform, you will need to write your
+own platform file, and modify the top part of
+.I Imake.tmpl
+slightly.
+If you are doing a new port of X,
+.I or
+porting the X configuration files for use with a different project, you
+are well-advised to study all of the configuration files thoroughly.
+Ignorance is not bliss in such instances.
+.LP
+.I Imake.tmpl
+contains an #include line for each of the other four configuration files and
+for the
+.I Imakefile
+in the current directory.
+It also contains in-line sections for global constant definitions,
+header block selection, description of system characteristics, build
+definitions, and extra
+.I make
+rules.
+The template is
+structured as follows to make everything fit together:
+.LP
+.TS
+box tab (%) ;
+l l s l l
+l _ _ _ l
+l | l l s | l
+l | l l s | l
+l | l _ l | l
+l | l | l | l | l
+l | l _ l | l
+l | l _ l | l
+l | l | l | l | l
+l | l _ l | l
+l | l l l | l
+l | l l l | l
+l | l _ l | l
+l | l | l | l | l
+l | l _ l | l
+l | l _ l | l
+l | l | l | l | l
+l | l _ l | l
+l | l _ l | l
+l | l | l | l | l
+l | l _ l | l
+l | l l s | l
+l _ _ _ l .
+\h'.01i'%Imake.tmpl:%\h'.01i'%\h'.01i'
+%
+%\h'.01i'%global constants
+%%header blocks
+%%
+%%#include <\fIplatform\fR.cf>
+%%
+%%
+%%#include <site.def>
+%%
+%%system description and
+%%build definitions
+%%
+%%#include <Project.tmpl>
+%%
+%%
+%%#include <Imake.rules>
+%%
+%%
+%%#include "./Imakefile"
+%%
+%%extra \fImake\fR rules
+%
+.TE
+.LP
+Before these sections of the template are described, there are some general
+principles that should be kept in mind.
+.LP
+Much of the flexibility of the X configuration files is achieved
+through the use of the following construct, which defines
+.I symbol
+only if it has not already been defined:
+.Ds
+#ifndef \fIsymbol\fR
+#define \fIsymbol value\fR
+#endif
+.De
+This construct allows any system-, build- or project-related symbol to
+be given a default definition if none has been supplied earlier;
+coupled with support for inclusion of platform- and site-specific
+files prior to the section in which the default is defined,
+the default may be overridden
+by a definition occurring within those files.
+For example, the default for the C compiler symbol occurs in the build
+definitions section of
+.I Imake.tmpl
+and is defined thus:
+.Ds
+#ifndef CcCmd
+#define CcCmd cc
+#endif
+.De
+If the GNU C compiler is to be used instead, the default definition
+can be overridden
+simply by putting the following in
+.I site.def :
+.Ds
+#ifndef CcCmd
+#define CcCmd gcc
+#endif
+.De
+Use of the #ifndef/#endif construct is pervasive throughout the X11R4
+configuration files, to a much greater extent than in the X11R3 files.
+This is especially true in the platform-specific files.
+.LP
+A fairly consistent pattern followed within the system/build section of
+.I Imake.tmpl
+and within
+.I Project.tmpl
+is that definitions for
+.I cpp
+symbols are listed first, followed by definitions for
+.I make
+variables.
+I presume this is done because there is greater flexibility
+available in defining
+.I cpp
+symbols, e.g., through #ifndef conditional testing.
+Since
+.I cpp
+can't tell whether a
+.I make
+variable has previously been defined, the strategy adopted is to associate a
+.I cpp
+symbol with a given
+.I make
+variable thus:
+define the symbol conditionally to allow the possibility of
+overriding, then equate the
+variable to whatever value the symbol finally ends up with.
+For instance,
+.I Imake.tmpl
+contains:
+.Ds
+#ifndef CcCmd
+#define CcCmd cc
+#endif
+.sp .3v
+\&. . .
+.sp .3v
+CC = CcCmd
+.De
+If no earlier definition of CcCmd overrides the default
+CC ends up as
+``cc''.
+On the other hand, if the default is overridden to use ``gcc''
+instead (e.g., in
+.I site.def ),
+CC ends up as ``gcc''.
+.LP
+Sometimes ``mixed'' symbol definitions occur, in which
+.I cpp
+symbols are defined in terms of
+.I make
+variables.
+There are at least two reasons to do this.
+.IP (1)
+To avoid order-of-definition problems.
+Consider the two sets of definitions below.
+.Ds .IP
+.ta 3i
+#ifndef a #ifndef a
+#define a b #define a ${B}
+#endif #endif
+A = a A = a
+.sp .3v
+\&. . . . . .
+.sp .3v
+#ifndef b #ifndef b
+#define b z #define b z
+#endif #endif
+B = b B = b
+.De .IP
+What ends up in the
+.I Makefile
+is:
+.Ds .IP
+.ta 3i
+A = b A = ${B}
+B = z B = z
+.De .IP
+The example on the left is dependent on the order in which a and b are
+defined.
+As written above, a (and hence A) is defined in terms of
+a symbol that hasn't been defined yet; both get the value of a
+literal ``b''.
+The example on the right works; b is defined as ``z'', B gets
+the same value.
+A becomes ``${B}'', which is not evaluated further until
+.I make
+is run.
+At that time A evaluates properly to ``z'', independently of the order in
+which a and b are defined in the configuration file.
+.IP (2)
+To allow for greater flexibility at installation time.
+For example, UsrLibDir and USRLIBDIR are defined as:
+.Ds .IP
+#ifndef UsrLibDir
+#define UsrLibDir $(DESTDIR)/usr/lib
+#endif
+.sp .3v
+\&. . .
+.sp .3v
+USRLIBDIR = UsrLibDir
+.De .IP
+Symbols such as IncRoot, BinDir, AdmDir are defined similarly, even
+though DestDir (to which DESTDIR is eventually equated) is defined
+earlier (i.e., there is no order-of-definition problem here).
+If a user wants the install to take place under a different root than
+DestDir, the command ``make DESTDIR=/alternate/root install''
+suffices, by overriding the definition of DESTDIR in the
+.I Makefile .
+If UsrLibDir, etc., were defined directly in terms of DestDir rather
+than DESTDIR, this would not be possible.\**
+.FS
+Actually, it would be possible, but cumbersome: ``make install
+BINDIR=/alt/bin/dir ADMDIR=/alt/adm/dir LIBDIR=/alt/lib/dir ...''
+.FE
+.LP
+Each of the sections of
+.I Imake.tmpl
+is described below.
+The descriptions only contain representative examples of the symbols
+used in each configuration file.
+For exhaustive (and exhausting?) lists, consult the appendix.
+.NH 2
+Global constant definitions
+.LP
+This section of
+.I Imake.tmpl
+defines two symbols (YES as 1 and NO as 0).
+References to these symbols are legion
+throughout the rest of the configuration
+specification and their values should not be changed.
+.LP
+Note: symbols #define'd in the configuration files or the
+.I Imakefile
+have nothing to do with symbols #define'd in your programs; they
+are entirely independent.\**
+.FS
+I once wondered about this, which seems pretty ridiculous now.
+.FE
+.NH 2
+Header block selection
+.LP
+The header block section of
+.I Imake.tmpl
+determines the type of machine on which
+.I imake
+is being run.
+This is done by looking for a
+.I trigger \*-a
+.I cpp
+preprocessor symbol that uniquely and unambiguously indicates a given platform.
+For instance,
+``sun'' is defined only on Sun systems, ``apollo'' only on Apollo systems,
+and
+``ultrix'' is only on Ultrix systems.
+Their header blocks look like this:
+.Ds
+.ta 3i
+\fBSun:\fR \fBUltrix:\fR
+#ifdef sun #ifdef ultrix
+#define MacroIncludeFile <sun.cf> #define MacroIncludeFile <ultrix.cf>
+#define MacroFile sun.cf #define MacroFile ultrix.cf
+#undef sun #ifdef vax
+#define SunArchitecture #undef vax
+#endif /* sun */ #define VaxArchitecture
+ #endif
+\fBApollo:\fR #ifdef mips
+#ifdef apollo #undef mips
+#define MacroIncludeFile <apollo.cf> #define MipsArchitecture
+#define MacroFile apollo.cf #endif
+#undef apollo #undef ultrix
+#define ApolloArchitecture #define UltrixArchitecture
+#endif /* apollo */ #endif
+.De
+The trigger symbol might be predefined by
+.I cpp
+itself; if no such predefined symbol is available,\**
+.FS
+A goal ANSI C will help us reach?
+.FE
+.I imake
+is built to explicitly pass a definition for one to
+.I cpp
+to cause the correct header block to be selected.
+.LP
+If no trigger is defined, a generic configuration
+header block is selected instead.
+Since that means the platform wasn't
+properly determined, a warning is written into the
+.I Makefile :
+.Ds
+# WARNING: Imake.tmpl not configured; guessing at definitions!!!
+# This might mean that BOOTSTRAPCFLAGS wasn't set when building imake.
+.De
+The resulting generically-configured
+.I Makefile
+will probably fail in one of a number of strange and wondrous ways when
+used to try to build anything,
+With any luck, the hapless user will examine the
+.I Makefile
+to figure out
+what went wrong, see the warning, and realize that the platform wasn't
+determined properly.
+.LP
+Failure to find a defined trigger symbol might occur because no
+port exists for the machine in question, and thus no header block for
+it exists.
+(Each time X is ported, a header block for the new platform is added
+to this section of
+.I Imake.tmpl .)
+Failure will also occur if
+.I imake
+was not built properly (i.e., it doesn't pass the
+proper trigger symbol definition to
+.I cpp ).
+.LP
+Assuming the proper header block is selected, several
+things happen inside of it.
+The name of the associated platform-specific
+.I .cf
+file is defined for later inclusion by the template; one or more architecture
+indicator symbols are defined that can be used
+by later configuration sections
+to test for particular software or hardware platforms;
+the trigger symbol is undefined so it won't trigger any other header
+block.
+.LP
+A header block may define a single architecture indicator symbol that refers
+both to the software and hardware,
+or separate indicators may be defined for an operating system that
+runs on multiple hardware types,
+For example, ``ultrix'' indicates an Ultrix system, but it is no longer
+true (as it once was) that a VAX can be assumed as the hardware
+platform\*-RISC Ultrix systems run on MIPS chips now.
+Thus UltrixArchitecture is defined as the software indicator symbol, and
+VaxArchitecture or MipsArchitecture as the hardware indicator.
+.LP
+Software indicator symbols should be unique.
+Hardware indicator symbols are not necessarily unique in themselves
+and may be shared across different software
+platforms, e.g., MipsArchitecture can be defined for Ultrix or SGI systems,
+VaxArchitecture for Ultrix or BSD systems.
+.LP
+.I Imakefiles
+should always test for indicator symbols rather than trigger symbols,
+since the former are more reliable (the latter are undefined by the
+header block, anyway).
+.LP
+The use of predefined or
+.I imake -supplied
+.I cpp
+trigger symbols is fraught with peril, and one must construct the
+header blocks carefully, for two reasons:
+.IP (1)
+Symbols may be ambiguous.
+For instance, ``vax'' can be defined both under Ultrix and under BSD.
+Thus, the Ultrix header block must come first.
+It tests for ``ultrix'' and if that succeeds, defines UltrixArchitecture
+and undefines ``vax'' so the BSD block will fail.
+.IP (2)
+Symbols may become ambiguous in unanticipated ways in the
+future.
+The ``mips'' symbol is an example.
+In R3 it was used to unambiguously detect a true MIPS machine.
+This can no longer be done given the presence of that symbol on other
+systems that also run on MIPS chips now.
+.LP
+When porting X to other platforms, it is sometimes
+difficult to know either what the trigger symbol should be, or what
+indicator symbol(s) to use.
+Consider MIPS machines running RISC/os.
+``mips'' is insufficient as a trigger, because it is does not
+unambiguously define MIPS systems.
+The hardware indicator symbol is clear enough, MipsArchitecture, but
+the software indicator is less so.
+The name of the MIPS operating system suggests that
+RiscosArchitecture might be a good choice.
+Guess again.
+Acorn Computers Ltd. has an OS with a similar name, ``RISC OS''.\**
+.FS
+My own preference is to use ``mipsriscos'' as the trigger symbol,
+MipsArchitecture as the hardware indicator,
+and MipsRiscosArchitecture
+(which seems suitably unique, but has the disadvantage of being quite
+long, and uneuphonious to boot) as the software indicator.
+MIPS Computers now claims to consider ``RISCOS'' their trigger symbol.
+.FE
+.NH 2
+platform.cf
+.LP
+After the header block section has determined which platform-specific
+file to use, that file is then included by
+.I Imake.tmpl :
+.Ds
+/**/################################################################
+/**/# platform-specific configuration parameters - edit MacroFile to change
+#include MacroIncludeFile
+.De
+where MacroIncludeFile has been defined properly by the header block.
+.LP
+The platform file contains definitions needed to make X build and
+install correctly on a particular system.
+Some common things found here are definitions for the operating
+system name version numbers (major and minor), C compiler version
+numbers, and workarounds for missing commands.
+Overall, these files are really quite a hodgepodge of different things,
+and it is difficult to describe them in any general way.
+You should read through the
+.I .cf
+file for your system before you try to compile anything, to get an
+idea what can be done with it.
+(It doesn't hurt to read
+.I all
+the
+.I .cf
+files, as a matter of fact, especially if you are doing a new port.)
+.LP
+It is important that version numbers in the platform file
+accurately reflect your system.
+Some symbol values are contingent upon the OS or C
+compiler version, to accommodate system changes, deficiencies, or
+bugs, so you want to make sure you get the right definitions.
+For example,
+.I sun.cf
+contains the following:
+.Ds
+#if OSMajorVersion <= 3
+#define HasVoidSignalReturn NO
+#else
+#define HasVoidSignalReturn YES
+#endif
+.De
+This reflects a change in the return type of the
+.I signal()
+system call (from
+.I int*
+to
+.I void* )
+on Sun systems beginning with SunOS 4.0.
+Ultrix systems underwent a similar change between 3.0 and 3.1 but the
+.I ultrix.cf
+file doesn't yet reflect the change.
+Perhaps in R5.
+.LP
+A common missing-command workaround occurs for those systems
+that have no BSD-compatible
+.I install
+command, such as in
+.I cray.cf :
+.Ds
+#define InstallCmd sh $(SCRIPTSRC)/install.sh
+.De
+It is important to set the value of the SystemV symbol to either YES or NO
+in the platform file because
+(1) the value of parameters defined in
+.I site.def
+may depend on it, and the default value is not set until
+the system/build definition section (i.e., after
+.I site.def );
+(2)
+the default values of many parameters in later parts of the template
+depend on the value of SystemV.
+For instance, there is usually no
+.I ranlib
+under System V, so the default is defined as a no-op:
+.Ds
+#ifndef RanlibCmd
+#if SystemV
+#define RanlibCmd /bin/true
+#else
+#define RanlibCmd ranlib
+#endif
+#endif
+.De
+It is perhaps safer to rely on predefined
+.I cpp
+symbols (should they exist) in the platform-specific files
+than in the header block section of
+.I Imake.tmpl .
+Once you know the system type, the universe of such
+symbols is more constrained and their meanings cannot clash with those
+of symbols defined on other vendors' systems.
+.LP
+The platform files were significantly reorganized between R3 and R4.
+In R3, each platform file was expected to contain a definition for
+each of the build parameters (C compiler, loader, link command,
+etc.).
+Whenever a change was made that affected one platform file, such as
+defining a new symbol, it usually affected them all.
+Since the definitions were usually broadly similar across platforms,
+this was more work than necessary.
+The approach adopted in R4 is to supply best-guess values as the
+default definitions for these parameters in the template, which
+individual platform files may override as necessary.
+This set of defaults defines a baseline configuration.
+There are two advantages to this method.
+The platform files need only specify where they
+.I differ
+from the baseline, by overriding the default definitions; and changes or
+additions to the baseline usually require retrofitting of only a few
+platform files.
+.NH 2
+site.def
+.LP
+This file contains site-specific definitions.
+It is used to reflect local site-wide conventions.
+Should you wish to override the defaults,
+this is the place to indicate installation directories, whether to
+build the server and example programs, any special versions of
+programs to use during the build, etc.
+.LP
+The name
+.I site.def
+seems, to me at least, something of a misnomer.
+For instance, one of the things that is likely to be set there
+is HasLargeTmp, to indicate whether you have a large temp file
+directory.
+.I site.def
+is the place for this definition (it depends on your particular
+file system layout, so it doesn't go in the platform-specific file,
+and it's not
+.I cpp -guessable,
+so it doesn't go in the system description section).
+But a ``site'' can be a location at which multiple hosts
+are administered, and which may be configured dissimilarly.
+Some may have a large temp directory, others may not.
+Similarly,
+.I site.def
+is the logical place to specify that you want to use the GNU C
+compiler,
+but you might not necessarily want to use it on all hosts at a site.
+In some ways
+.I host.def
+might be a better name for this file.
+.NH 2
+System description and build parameter definitions
+.LP
+The platform- and site-specific files are followed by a section containing
+a number of default definitions.
+Generally, these describe system characteristics
+(e.g., does it have
+.I vfork() ?
+does it have sockets?) or are related to management of the
+build and installation\**
+.FS
+Viz.,
+.I how
+things should be installed, not
+.I where ;
+defaults for the latter are in
+.I Project.tmpl .
+.FE
+processes (e.g., what is the name of the C compiler?
+does the loader need any special flags?).
+These are not X issues and so are segregated into their own section.
+.LP
+This section of
+.I Imake.tmpl
+should not be modified; definitions should be overridden
+in platform- or site-specific files.
+.NH 2
+Project.tmpl
+.LP
+This
+file contains definitions for parameters that are specific to X.
+Examples: whether to build debuggable versions of libraries, the
+screen resolution, what sorts of connections to accept (UNIX, TCP
+or DECnet sockets), where programs or libraries should be installed.
+.LP
+A number of the
+.I make
+variables in
+.I Project.tmpl
+are directory locations.
+Most of them are named in one of two ways, \fIXXX\fRDIR or \fIXXX\fRSRC.
+Variables of the first form are defined by equating them to the
+values
+.I cpp
+symbols having similar names (e.g., LIBDIR=LibDir).
+The
+.I cpp
+symbols are defined in the usual default-provided-but-override-allowed
+manner,
+because they refer to where things are to be placed
+at installation time, something which the installer might wish to
+change.
+.LP
+Variables of the second form, \fIXXX\fRSRC, indicate the layout of various
+source directories within the X distribution.
+They are not supposed to be changed, so there is no provision for
+overriding them; rather than being equated to
+.I cpp
+symbols, they are simply defined
+directly (e.g., SERVERSRC=$(TOP)/server).
+.LP
+.I Project.tmpl
+should not be modified; definitions should be overridden
+in platform- or site-specific files.
+.NH 2
+Imake.rules
+.LP
+This file contains
+.I cpp
+macros used to generate
+.I make
+rules from concise descriptions of targets and dependencies.
+Since all the
+.I cpp
+symbol substitution functionality is available, these macros can be
+very powerful and are sometimes quite complicated.
+.LP
+.B Example:
+A simple rule to compile a program might be (this isn't an actual X
+rule):
+.Ds
+.ta .5i +4i
+# define CompileProgram(program,objects,libraries)
+program: objects
+ cc \-o program objects libraries
+.De
+If invoked in an
+.I Imakefile
+as ``CompileProgram (xproga, main.o, \-lm)'', this macro would expand in the
+.I Makefile
+to:
+.Ds
+.ta .5i
+xproga: main.o
+ cc \-o xproga main.o \-lm
+.De
+The invocation
+``CompileProgram (xprogb, main.o parse.o scan.o, \-lm \-ll \-ly)''
+would expand to:
+.Ds
+.ta .5i
+xproga: main.o parse.o scan.o
+ cc \-o xproga main.o parse.o scan.o \-lm \-ll \-ly
+.De
+There is one problem with these examples, which is that the CompileProgram()
+macro definition spans multiple lines, and
+.I cpp
+macros are normally single-line.
+One can can write multiple-line macros by putting a ``\e'' at the end
+of lines to be continued onto the next, but this doesn't work for
+.I imake's
+purpose since
+.I cpp
+will still collapse the expanded macro onto a single (possibly quite long)
+line.
+That makes
+.I make
+quite unhappy.
+.LP
+To get around this, special place markers ``@@\e'' are used on all
+lines of a rule definition but the last.
+The ``\e'' allows multiple-line definitions for
+.I cpp
+and the ``@@'' lets
+.I imake
+know how to postprocess
+.I cpp
+output in order to split expanded macros back up into multiple lines
+suitable for
+.I make .
+This keeps both
+.I cpp
+and
+.I make
+happy.
+.LP
+So:
+the
+.I real
+way to write the CompileProgram() macro is:
+.Ds
+.ta .5i +4i
+# define CompileProgram(program,objects,libraries) @@\e
+program: objects @@\e
+ cc \-o program objects libraries
+.De
+The invocation ``CompileProgram (xproga, main.o, \-lm)'' comes out of
+.I cpp
+looking like this:
+.Ds
+xproga: main.o @@ cc \-o xproga main.o \-lm
+.De
+.I imake
+sees the ``@@'' and knows it has to break the line back up to
+produce the intended result.
+.LP
+In short,
+the purpose of the strange syntax is to keep
+.I cpp
+from totally destroying the usefulness of the output for
+.I make
+purposes.
+Thus, although
+.I imake
+relies heavily on
+.I cpp ,
+one of
+.I imake 's
+jobs is to undo some of the damage done by
+.I cpp \*-an
+uneasy alliance indeed.\**
+.FS
+This use of ``@@\e'' seems quite natural and obvious, now that I have worked
+with it for a while.
+I remember, though, that the first few times I looked at the X
+.I imake
+rules, especially the more complicated ones,
+the formatting and syntax seemed so bizarre to me that
+a switch flipped in my brain, which then refused to comprehend
+anything at all.
+Repeated exposure gradually inured me to the infelicities of the
+syntax.
+.FE
+.LP
+All the macro definitions in
+.I Imake.rules
+are embedded within the standard override construct:
+.Ds
+#ifndef \fIrulename\fR
+#define \fIrulename\fR .\0.\0.
+#endif
+.De
+Thus, even rules are subject to being overridden.
+If a rule needs to be overridden for a particular platform,
+the default definition will be placed in the
+platform-specific
+file (\fIsgi.cf\fR does this).
+If a rule only needs redefining in a single directory, it may be
+better to undefine it and redefine right it in that directory's
+.I Imakefile
+(see
+.I mit/config/Imakefile
+for an example).
+.LP
+In R3, rule definitions were not bracketed within #ifndef/#endif pairs.
+This meant that although individual
+.I Imakefiles
+could undefine and redefine rules, platform files could not.
+Any definition of a rule in a platform file would be unconditionally replaced
+by the definition in
+.I Imake.rules
+(possibly accompanied by a ``symbol redefined'' message).
+The R4 architecture is an improvement because it is not
+constrained by this limitation.
+.LP
+.I Imake.rules
+should not be modified; definitions should be overridden
+in platform- or site-specific files.
+.NH 2
+\&./Imakefile
+.LP
+The last file included by the template is the
+.I Imakefile
+from the current directory.
+As already mentioned,
+.I imake
+causes
+.I make
+comments in this file to be made
+.I cpp -safe
+by preceding them with ``/**/'' if necessary.
+The
+.I Imakefile
+indicates targets to be built and installed, and their
+dependencies, in terms of the
+.I cpp
+macros defined in
+.I Imake.rules .
+There may also be targets for generating dependencies, creating
+installation directories, creating lint libraries or tag files, etc.
+.LP
+.I Imakefile -writing
+is described in more detail in a later section.
+.NH 2
+Extra make rules
+.LP
+The last section of
+.I Imake.tmpl
+adds some common targets to the
+.I Makefile ,
+such as a ``Makefile'' target to regenerate the
+.I Makefile
+itself, and default ``tags'' and ``clean'' targets.
+If the directory has subdirectories, rules to
+recurse through them for the ``install'', ``install.man'', ``clean'',
+``tags'', ``Makefiles'' and ``includes'' targets are generated.
+These rules are added if the
+.I cpp
+symbol IHaveSubdirs is defined and the
+.I make
+variable SUBDIRS is equated to the list of subdirectories in the
+.I Imakefile .
+.NH
+Building imake
+.LP
+Before you can build any part of X,
+.I imake
+itself must be built.
+``make World'' in the top-level X source directory builds
+.I imake
+automatically (in
+.I mit/config ).
+The following discussion explains what happens during that process and
+some of the things you may need to do in preparation for the ``World''
+build.
+You want to read this section if ``make World'' dies when you try it, or you
+want to port X to another platform,
+or you want to build
+.I imake
+or adapt the X configuration files for use with other projects.
+You need to look at the following files:
+.I Makefile.ini ;
+.I imakemdep.h ;
+.I Imake.tmpl .
+.NH 2
+Determine what you are trying to accomplish
+.LP
+When you build
+.I imake
+you want to
+(1) get it to compile successfully, so you can use it;
+(2) guarantee that it makes sure
+.I cpp
+knows the trigger symbol\*-whether
+.I cpp
+predefines it or not\*-so you don't end up with generically-configured
+.I Makefiles .
+.LP
+Conspiring to keep you from your goal are three dilemmas.
+.IP \(bu
+.I imake
+generates
+.I Makefiles
+for use in compiling programs;
+.I imake
+is compiled using a
+.I Makefile .
+.IP \(bu
+.I imake
+needs to know your system's trigger symbol in order to pass it along to
+.I cpp
+for proper
+.I Makefile
+generation.
+But
+.I imake
+doesn't know the trigger itself if neither
+.I cc
+nor
+.I cpp
+predefine it.
+.IP \(bu
+Some systems require special C compiler flags to ensure proper
+compilation of all but the most trivial programs.
+One of the facilities provided by
+.I imake -generated
+.I Makefiles
+is that these flags can be automatically specified.
+Of course, that is small consolation when the program to be compiled is
+.I imake \*-which
+happens to be just such a non-trivial program itself.
+.LP
+The solution to the first dilemma is to use a minimal handwritten file
+.I Makefile.ini
+instead.\**
+.FS
+There might be a
+.I Makefile
+in
+.I mit/config
+already,
+but it might not have been generated on your system, so it's not safe to
+use.
+It has a bug in it, anyway.
+.FE
+You might need to hack
+.I Makefile.ini
+file slightly for your system\*-but only slightly.
+If you find yourself making large changes, that is a symptom you don't
+understand what you're supposed to be doing.
+Stop and think some more first.
+.LP
+The second and third dilemmas are solved by manually passing the trigger symbol
+to the
+.I imake
+compilation and using a small bootstrap program that knows what
+special flags are necessary to get
+.I imake
+to compile without error.
+The commands in
+.I Makefile.ini
+that build
+.I imake
+look something like this:\**
+.FS
+The commands actually use CFLAGS, which includes BOOTSTRAPCFLAGS as part
+of its definition; you get the idea.
+.FE
+.Ds
+$(CC) \-o ccimake $(BOOTSTRAPCFLAGS) ccimake.c
+$(CC) \-o imake $(BOOTSTRAPCFLAGS) imake.c `./ccimake`
+.De
+BOOTSTRAPCFLAGS is the
+.I make
+variable used to pass the trigger value for your system to
+.I ccimake
+and
+.I imake
+so they know the platform type.
+It is typically ``BOOTSTRAPCFLAGS=\-D\fItrigger\fR''
+if your
+.I cpp
+doesn't predefine the trigger, empty otherwise.\**
+.FS
+The BOOTSTRAPCFLAGS mechanism was not present in some earlier versions
+of X11 (e.g., R1).
+The number of systems to which X had been ported then was smaller and
+all of them had
+.I cpp 's
+that predefined a unique symbol.
+.FE
+.LP
+.I ccimake
+is the bootstrap program.
+It is\*-by design\*-so simple that it should compile
+without any special treatment, and is used to figure out any extra
+flags needed on your platform to get
+.I imake
+to compile.
+BOOTSTRAPCFLAGS is supplied to the
+.I ccimake
+build so it can select the necessary flags by platform type.
+.LP
+.I imake
+is built using the flags supplied by
+.I ccimake ,
+so that it compiles correctly, and with the
+the trigger value supplied in BOOTSTRAPCFLAGS,
+so that it learns and memorizes the trigger for
+itself.
+When
+.I imake
+passes the trigger to
+.I cpp ,
+that in turn allows
+.I cpp
+to properly determine the correct header block in
+.I Imake.tmpl
+when
+.I Makefiles
+are generated.
+.NH 2
+Lay the groundwork
+.LP
+First, you need to determine what the trigger symbol is for your system,
+as well as the value of BOOTSTRAPCFLAGS.
+For existing ports, you can find out the trigger symbol by
+examining the header block section of
+.I Imake.tmpl .
+The value of BOOTSTRAPCFLAGS can be found in the platform
+.I .cf
+file for your system.
+Look for a line that defines BootstrapCFlags; if
+.I cpp
+predefines the trigger, there will likely be no such line.
+This means BOOTSTRAPCFLAGS is empty.
+Otherwise the value will probably be ``\-D\fItrigger\fR'', e.g.,
+``\-DmacII'', ``\-Datt'', ``\-Daix''.
+.LP
+A complication likely to arise in the future with regard to
+predefined preprocessor symbols is that ANSI C takes a dim view of
+all (or almost all) such.
+BOOTSTRAPCFLAGS is likely
+to be non-empty on more systems as implementations of ANSI C become
+distributed more widely.
+.LP
+For new ports, you need to invent a trigger symbol
+that uniquely identifies your system and define
+BOOTSTRAPCFLAGS accordingly.
+Suppose you have a Brand X system.
+You can use ``brandx'' as the trigger and ``BOOTSTRAPCFLAGS=\-Dbrandx''.
+You also must modify
+.I imakemdep.h .
+This header file is #include'd by three programs,
+.I ccimake ,
+.I imake
+and
+.I makedepend ,
+and has one section for each.\**
+.FS
+.I Imake.tmpl
+contains some comments near its beginning pertaining to new ports.
+These indicate that
+.I imake.c ,
+and
+.I main.c
+in the
+.I makedepend
+source, should be modified.
+These comments are correct for R3 but evidently were not updated for R4;
+in both cases the modifications should be made to
+.I imakemdep.h .
+Similarly, the
+.I README
+file refers to
+.I ccflags.c ,
+the R3 equivalent of
+.I ccimake.c .
+.FE
+.LP
+The first section of
+.I imakemdep.h
+pertains to
+.I ccimake ;
+it consists of a bunch of #ifdef/#endif blocks that define
+.I imake_ccflags
+according to the trigger symbol.
+.I imake_ccflags
+is defined as the flags needed to compile
+.I imake
+on your platform.
+For instance, if your Brand X system is System V-based, you need to
+specify that:
+.Ds
+#ifdef brandx
+#define imake_ccflags "\-DSYSV"
+#endif
+.De
+.I ccimake
+simply writes the value of
+.I imake_ccflags
+to its standard output.
+Common flags in this definition are \-DSYSV or \-DUSG to indicate System
+V or USG systems.
+Other flags might also be necessary\*-see the ``hpux'' and ``umips''
+blocks for some particularly unpleasant examples.
+If no special flags are necessary to compile
+.I imake
+(e.g., under Ultrix or BSD),
+there need not be any block for your system, and
+.I ccimake
+simply writes out a default definition of
+.I imake_ccflags
+(currently \-O).
+.LP
+You might have to fool around trying to compile
+.I imake
+by hand to determine the correct flags before you know how to define
+.I imake_ccflags .
+.LP
+The second section of
+.I imakemdep.h
+is for
+.I imake .
+It too has a set of #ifdef/#endif blocks, this time to select a
+trigger symbol definition based on the trigger symbol.
+That sounds circular and it is.
+These blocks add entries to
+.I cpp_argv [\|],
+which is an array of strings to be passed to
+.I cpp
+by
+.I imake .
+If your
+.I cpp
+predefines the correct trigger symbol automatically, you don't need to
+do anything to this.
+Otherwise, this is where you want your trigger symbol to be listed,
+and there should be a block something like this:
+.Ds
+#ifdef brandx
+ "\-Dbrandx", /* for Brand X systems */
+#endif
+.De
+This causes
+.I imake
+to pass ``\-Dbrandx'' to
+.I cpp
+to make it simulate predefinition of the trigger.
+When
+.I cpp
+reads the configuration files the trigger will have been defined and
+the correct header block in
+.I Imake.tmpl
+will be selected.
+.LP
+Following the sections for
+.I ccimake
+and
+.I imake ,
+.I imakemdep.h
+contains a third section for
+.I makedepend
+(the compiled version; if you use the shell script version of
+.I makedepend
+in
+.I mit/util/scripts ,
+this section of
+.I imakemdep.h
+is irrelevant).
+It looks for various system- and compiler-related definitions that may
+be predefined by
+.I cc
+and/or
+.I cpp .
+.I makedepend
+uses this information to be smart.
+Consider the following C program fragment:
+.Ds
+#ifdef ultrix
+#include "inca.h"
+#else
+#include "incb.h"
+#endif /* ultrix */
+.De
+If ``ultrix'' is defined,
+.I makedepend
+knows to generate a dependency for ``inca.h'' and not
+``incb.h'';
+a dumb
+.I makedepend
+has to to assume dependencies on both.
+.LP
+It's easiest simply to leave this section of
+.I imakemdep.h
+alone.
+.NH 2
+Build the program
+.LP
+You're ready to begin (this should actually be simple if you've done
+the above correctly).
+The first thing to do is ensure the absence of any detritus that might
+be laying around from previous builds:
+.Ds
+make \-f Makefile.ini clean
+.De
+Then build
+.I ccimake
+and
+.I imake .
+If your
+.I cpp
+predefines the trigger, you can build with:
+.Ds
+make \-f Makefile.ini
+or
+make \-f Makefile.ini BOOTSTRAPCFLAGS=
+.De
+Otherwise, specify the trigger explicitly.
+E.g., for Brand X, use:
+.Ds
+make \-f Makefile.ini BOOTSTRAPCFLAGS=\-Dbrandx
+.De .NH 2
+Test your handiwork
+.LP
+If
+.I imake
+is supposed to pass a trigger symbol definition to
+.I cpp ,
+you should test whether it actually does or not by executing the
+following command (\fB\-T\fI/dev/null\fR provides an empty input template, and
+\fB\-s\fI/dev/null\fR throws away the output so it doesn't clobber the
+.I Makefile
+in your current directory):
+.Ds
+imake \-v \-T/dev/null \-s/dev/null
+.De
+.B \-v
+causes
+.I imake
+to print out the
+.I cpp
+command that it executes.
+If you don't see a \-D\fItrigger\fR
+in that command,
+.I imake
+wasn't built properly.
+.NH 2
+Modifying other configuration files for a new platform
+.LP
+If you are developing a new port to another system,
+you have to do more than be able to compile
+.I imake ,
+you also need to be able to use it
+in conjunction with the configuration files.
+First, you must modify the header block section of
+.I Imake.tmpl
+to add a block for your system.\**
+.FS
+This is the only section of
+.I Imake.tmpl
+that should ever need modifying.
+Other changes would be specified in the platform-specific file for
+your system.
+.FE
+It will look something like this:
+.Ds
+#ifdef brandx
+#define MacroIncludeFile <brandx.cf>
+#define MacroFile brandx.cf
+#undef brandx
+#define BrandxArchitecture
+#endif /* brandx */
+.De
+Second, you must create a platform-specific file
+.I brandx.cf .
+If your bootstrap flags are non-empty, this should contain, at
+minimum, ``#define BootstrapCFlags \-Dbrandx''.
+Most certainly it will have other things in it, too.
+You will discover just what as you go through the process
+of porting the server and/or clients.
+.NH
+Building X Itself, or, When Is BOOTSTRAPCFLAGS Necessary?
+.LP
+The question addressed in this section is:
+how can you get all the
+.I Makefiles
+built?
+(This document is really about configuring X, not building it, and
+configuring X amounts to building the
+.I Makefiles .)
+.LP
+If you have gotten this far, you know you can get
+.I imake
+compiled and can proceed to build X itself.
+.I "Before you do anything else,"
+copy the top-level
+.I Makefile
+somewhere safe (outside of the source tree).
+If something goes wrong and this file gets trashed,
+you want to be able to recover it.
+You're asking for trouble if you don't.
+.LP
+The ``do everything'' operation in building X is ``make World''.
+It builds
+.I imake ,
+generates all the
+.I Makefiles ,
+removes extraneous object files, builds the header file tree,
+generates dependencies, and compiles everything.
+The interesting parts of this
+from a configuration perspective are the first two steps.
+.LP
+The important questions are: (1) what is the value of BOOTSTRAPCFLAGS;
+and (2) when
+must BOOTSTRAPCFLAGS be specified?
+You have already answered the first question by determining how to
+build
+.I imake ,
+so only the second is considered below.
+.LP
+When you build
+.I imake
+``manually'' in
+.I mit/config
+using
+.I Makefile.ini ,
+you must specify BOOTSTRAPCFLAGS explicitly if it is non-empty.
+What about when building from the top-level directory, e.g., ``make
+World''?
+It is a useful exercise to build
+.I imake
+by hand to test your understanding of the issues involved, but that
+won't help you to do the ``World'' build\*-the first thing
+``make World'' does, unfortunately, is throw
+.I imake
+away and rebuild it from scratch.
+.LP
+The X Release Notes (section 2) indicate that for
+``make World'' you should
+specify BOOTSTRAPCFLAGS if you find a definition for BootstrapCFlags in the platform
+.I .cf
+file (which means there is no unique predefined
+.I cpp
+symbol).
+By implication, you do not need to specify BOOTSTRAPCFLAGS
+if there is no value of BootstrapCFlags in your platform
+.I .cf
+file.
+This means essentially that the empty value ``BOOTSTRAPCFLAGS='' is sufficient to
+compile
+.I imake
+properly, which brings up a subtle point.
+Each
+.I Makefile
+created in the X distribution contains a line that says
+.Ds
+BOOTSTRAPCFLAGS=\fIsomething\fR
+.De
+where
+.I something
+is the default value for any
+.I make
+operation, and may or may not be empty.
+Thus, when you execute a command such as
+.Ds
+make World BOOTSTRAPCFLAGS=\-Dbrandx
+.De
+you are not just
+.I providing
+a value of BOOTSTRAPCFLAGS, you are also
+.I overriding
+the default value in the
+.I Makefile .
+.LP
+The implication that BOOTSTRAPCFLAGS need not be specified if
+BootstrapCFlags is
+not defined involves a hidden assumption, i.e., that BOOTSTRAPCFLAGS
+.I already
+has the empty value in the top-level
+.I Makefile .
+If you obtain your X distribution from a system on which X has been built
+and on which BOOTSTRAPCFLAGS is non-empty, that assumption is incorrect.
+If you don't explicitly provide an empty value by saying
+.Ds
+make World BOOTSTRAPCFLAGS=
+.De
+to override the default in the
+.I Makefile ,
+a value which is incorrect for your system is used instead.
+You can get some very strange results this way.
+.LP
+I submit that, in the general case, the deciding factor determining
+whether to specify BOOTSTRAPCFLAGS is not so much whether
+BootstrapCFlags is defined or not, but whether you've built your
+.I Makefiles
+yet.
+If not, you need to specify BOOTSTRAPCFLAGS,
+.I "even if it's empty."
+Otherwise, you don't have to.
+In practice, this means that when you are building X on a new system,
+you should assume BOOTSTRAPCFLAGS in the
+.I Makefile
+is incorrect and explicitly override it on the command line.
+Normally this will be on the first ``World'' build.
+.LP
+The Release Notes do not cover the general case.
+Rather, they assume you are working from a virgin distribution (where
+the default BOOTSTRAPCFLAGS is in fact empty).
+.LP
+Once the
+.I Makefiles
+have been built properly,
+BOOTSTRAPCFLAGS will be defined correctly in them and
+they will take care of propagating the right value
+for you automatically\*-forever, even into another operation that
+rebuilds
+.I imake
+and the
+.I Makefiles .
+You can test this for yourself on a machine that
+has a non-empty BOOTSTRAPCFLAGS.
+Do ``make World BOOTSTRAPCFLAGS=\-D\fItrigger\fR'', then ``make
+World''.
+You'll see during the ``make World'' that BOOTSTRAPCFLAGS is supplied for you.
+.LP
+.B "Note 1:"
+It is not necessary to do a ``World'' build to build
+.I imake
+and the
+.I Makefiles ;
+there is a ``mastermakefiles'' target that will do so.
+This is a far more modest undertaking than doing the ``World'' build
+and you can check a few of the
+.I Makefiles
+afterward to see if the ``World'' build is likely to succeed or not:
+If BOOTSTRAPCFLAGS is correct and the correct header block was selected,
+you can
+then go ahead and do ``make World'' without having to specify BOOTSTRAPCFLAGS.
+.LP
+.B "Note 2:"
+The above discussion assumes that if BOOTSTRAPCFLAGS is not empty, BootstrapCFlags is
+defined
+correctly in the platform
+.I .cf
+file, because BOOTSTRAPCFLAGS normally gets its value from that symbol when
+.I Makefiles
+are generated.
+.NH 2
+Alternatives ways of specifying BOOTSTRAPCFLAGS
+.LP
+There are two alternatives to specifying BOOTSTRAPCFLAGS explicitly
+on the
+command line when you build
+the
+.I Makefiles ,
+both sneaky and both deprecated.
+They are mentioned here in order to point out why you shouldn't use
+them.
+.LP
+First, you can edit
+.I config/Makefile.ini
+manually to set the value of BOOTSTRAPCFLAGS directly.
+The reason this is not a good idea is that if you give your X
+distribution to somebody else that doesn't have the same kind of
+machine, you've given away an explicitly misconfigured
+.I Makefile.ini .
+The recipient might fail to appreciate the subtle irony of this
+gesture.
+.LP
+Second, you can forget about BOOTSTRAPCFLAGS entirely.
+That's correct\*-you can build
+.I imake
+with wild abandon and total lack of regard for whether it knows about
+the correct trigger symbol or not.
+``But on some systems,
+.I imake
+must pass the trigger definition to
+.I cpp
+explicitly,'' you say, ``and
+.I imake
+compiled in such a reckless and irresponsible manner may not do the job.''
+Quite right.
+However...
+.I imake
+also examines your environment, and the value of IMAKEINCLUDE, if
+defined there, is passed to
+.I cpp .
+The value of IMAKEINCLUDE must begin with ``\-I'' (or
+.I imake
+will reject it), but you can be clever and set it
+to ``\-I. \-Dbrandx'' and the
+trigger symbol will be passed through to
+.I cpp
+and your
+.I Makefiles
+will build happily.
+.LP
+This is sneaky because it uses the environment to affect the
+build process in a way that is not evident.
+Worse yet, if you actually install an
+.I imake
+built this way, it won't work for anyone else who isn't privy to the
+IMAKEINCLUDE convention.
+.LP
+(A third alternative is to edit
+BOOTSTRAPCFLAGS to the proper value in the top-level
+.I Makefile
+before ``make World''.
+This is functionally equivalent to specifying it on the command line.)
+.NH
+Imakeconoclasm\*-X configuration bugs
+.LP
+Given the size of the X project, there are astonishingly few outright
+errors in the files involved in the configuration process.
+The ones I know about are listed below.
+.IP (1)
+Assume the following scenario.
+You do a ``make World''.
+This builds
+.I imake ,
+generates all the
+.I Makefiles ,
+cleans all the directories and finally builds the X stuff.
+.IP
+Then you decide to do some work in an X directory that requires the
+.I Makefile
+to be rebuilt, so you execute
+``make Makefile''.
+What happens?
+You might be surprised to observe that
+.I imake
+is rebuilt before your
+.I Makefile
+is regenerated.
+This reason is that the rules for the ``Makefile'' target check
+whether
+.I imake
+exists, and if not they build it first.
+Since the ``World'' build does a clean after generating the
+.I Makefiles ,
+.I imake
+was thrown away.
+.IP
+In fact,
+.I imake
+will be built the first time ``make Makefile'' is done after the
+``World'' build even if the
+cleaning had not been done.
+The rules that check for
+.I imake 's
+existence look for
+.I Makefile
+in
+.I mit/config/Makefile.ini
+and build
+.I imake
+with that if it's there.
+(It will be because the ``World'' build generates it.)
+But the dependency for
+.I imake
+in
+.I Makefile
+is
+.I imake.o
+while the dependency in
+.I Makefile.ini
+(with which
+.I imake
+is initially built) is
+.I imake.c .
+This means that even if
+.I imake
+is present in
+.I mit/config ,
+it will be built again because
+.I imake.o
+isn't.
+.IP
+That isn't actually a bug, but it can be confusing.
+Possibly even more confusing than the previous paragraph.
+.IP
+What
+.I is
+a bug is that
+.I Makefile
+in
+.I mit/config
+does not pass BOOTSTRAPCFLAGS to the
+.I imake
+compilation.
+If your BOOTSTRAPCFLAGS is non-empty, you end up with a bad
+.I imake.
+The fix is as follows:
+.Ds .IP
+Change:
+ DEFINES = $(SIGNAL_DEFINES)
+To:
+ DEFINES = $(SIGNAL_DEFINES) $(BOOTSTRAPCFLAGS)
+.De .IP (2)
+The IncRoot symbol is defined twice, once in
+.I Imake.tmpl
+and once in
+.I Project.tmpl .
+This is a minor nit, since it gets the same value in both files.
+However, if you use a copy of the configuration files as a base for your own
+projects, you will probably
+modify these files and you should be aware that changing the definition in
+.I Project.tmpl
+has no effect if you leave both definitions in.
+.IP (3)
+.I makedepend
+has some hardwired pathnames in the source code.
+This may bite you if you use
+.I gcc
+or compile on a MIPS system under the BSD environment, or on other
+systems that put include files somewhere other than
+.I /usr/include .
+.IP (4)
+The default value of ExecableScripts in
+.I Imake.tmpl
+should be given a value based on SystemV, not SYSV.
+.Ds .IP
+Change:
+ #ifndef ExecableScripts
+ #ifdef SYSV
+To:
+ #ifndef ExecableScripts
+ #ifdef SystemV
+.De .IP
+This is simply for consistency.
+Probably the right thing always happens anyway.
+.NH
+Writing Imakefiles.
+.LP
+.B
+This section is miserably incomplete.
+.LP
+This section assumes that
+.I imake ,
+.I makedepend
+and
+.I xmkmf
+are installed in a public directory somewhere, which implies the
+additional assumption that the
+configuration files are installed where
+.I xmkmf
+can get at them.
+Why make these assumptions?
+.LP
+Normally you work with both an
+.I Imakefile
+and a
+.I Makefile
+and after you make changes to the
+.I Imakefile ,
+you do ``make Makefile'' to regenerate the
+.I Makefile .
+You can use
+.I Makefile
+to rebuild itself this way because it has a
+``Makefile'' target in it containing rules to do so.
+.LP
+That doesn't work when you're starting from scratch with just
+.I Imakefile .
+This is where
+.I xmkmf
+comes in useful.
+Once you've written your
+.I Imakefile ,
+you just execute ``xmkmf'' and it will bootstrap a
+.I Makefile
+for you.
+Thereafter you can use ``make Makefile'' when
+.I Makefile
+needs rebuilding.
+.LP
+However, in order to bootstrap
+.I Makefile ,
+you need
+.I xmkmf .
+.I xmkmf
+assumes
+.I imake
+has been built and installed.
+If an installed
+.I imake
+is used, an installed
+.I makedepend
+must also be used.\**
+.FS
+To see why, you need to look at the ImakeDependency() and
+DependDependency() macros in
+.I Imake.rules .
+Notice that both macros depend on the value of UseInstalled, so if one
+is installed, the other must be as well.
+Also see the definitions of IMAKE and MAKEDEPEND in
+.I Project.tmpl .
+.FE
+And if installed versions of
+.I xmkmf ,
+.I imake
+and
+.I makedepend
+are used, they will expect the configuration files to have been
+installed.
+Hence the assumptions at the beginning of this section.
+.LP
+Stuff that should go in here.
+.Ds
+1) ComplexProgramTarget() all, program, install, install.man, depend,
+ lint, clean (still need CleanTarget())
+2) ComplexProgramTarget_{1,2,3}
+3) SimpleProgramTarget() = CPT with only single source file
+4) NormalProgramTarget()
+.De
+.LP
+Here is the simplest
+.I Imakefile :
+.Ds
+.ta 1i
+ \(<- that's it right over there
+.De
+That was easy.
+But what can you do with it?
+First, execute ``xmkmf'', and you'll have the corresponding
+.I Makefile .
+Then you can try a few operations such as ``make
+clean'', ``make'', ``make Makefile'' to see what happens.
+(Note in particular that last target and observe that
+you can get your first
+.I Makefile
+with ``touch Imakefile; xmkmf''.)
+.LP
+Since
+.I make
+actually executes correctly for all of those targets (or should,
+anyway), you can see that a lot of structure is supplied for you by
+the configuration files.
+If you look at the
+.I Makefile
+generated from the null
+.I Imakefile ,
+you might be surprised by the complexity of it.
+.LP
+To test the syntactic correctness of your
+.I Imakefile :
+.Ds
+xmkmf ; make Makefile
+.De
+This builds
+.I Makefile
+twice.
+.I xmkmf
+builds the
+.I Makefile
+from scratch and fails if the configuration is bad.
+.I make
+builds a new
+.I Makefile
+using the one built by
+.I xmkmf ,
+and fails if that one is not legal.
+(say how that can happen, e.g., spelling errors cause it.)
+This should not happen with a null
+.I Imakefile ,
+but it may very well happen when you're writing real ones.
+.NH 2
+Miscellaneous Observations
+.IP \(bu
+Don't forget ``make depend'' after ``make Makefile''.
+.IP \(bu
+If you intend to use
+.I if
+or
+.I for
+constructs in an
+.I Imakefile ,
+you are well advised to copy the way in which they
+are used in
+.I Imake.rules .
+(See the beginning of the
+.I Imake.rules
+section of the Appendix for some notes on
+.I if
+constructs.)
+.IP \(bu
+If you need to pass special \-D's to the C compiler, set the
+.I make
+variable DEFINES.
+If you need to pass special \-I's to the C compiler, set the
+.I make
+variable INCLUDES.
+These will be passed to compilations automatically in CFLAGS
+(see definitions of CFLAGS, ALLDEFINES and ALLINCLUDES in
+.I Imake.tmpl ).
+.IP \(bu
+Some rules may not work as you expect after changing
+.I Imakefile .
+In particular,
+problems can occur the first time you try ``make \fItarget\fR'' that
+mysteriously disappear the second time.
+As an instance of this,
+note that the following command lines are not always equivalent:
+.Ds
+make Makefile Makefiles
+make Makefile ; make Makefiles
+.De
+You normally want to build the ``Makefiles'' target when there are
+subdirectories.
+Suppose you add a new subdirectory.
+This is done by adding it to the definition of
+SUBDIRS in the current directory's
+.I Imakefile .
+You then need to rebuild the
+.I Makefile
+so that the definition of SUBDIRS is reset, and then rebuild
+.I Makefile
+in each of those subdirectories.
+The first command line above builds the ``Makefiles'' target using the
+(old) value of SUBDIRS from the (current)
+.I Makefile ,
+which is incorrect.
+The second command line rebuilds the
+.I Makefile ,
+then runs a second
+.I make
+process to build ``Makefiles''.
+The second process sees the (new) value of SUBDIRS in the (new)
+.I Makefile ,
+which includes the new subdirectory, and has the intended result.
+.IP
+What can be especially confusing is that if you executed ``make
+Makefile Makefiles'' twice, it would not do what you expected the
+first time, but it
+.I would
+the second time.
+.NH
+Courting disaster: How to do the wrong thing
+.LP
+.I imake
+is wonderful for portability when everything is configured
+properly.
+However, subtle syntax errors in the configuration files are often difficult
+to track down when you begin to make any significant changes to them.
+This section describes some of the misfortunes that may beset you
+should you make so bold as to engage in such an endeavor.
+.LP
+For X, the source of problems might be in any of
+.I Imakefile ,
+.I Imake.rules ,
+.I Imake.tmpl ,
+the platform
+.I .cf
+file, or
+.I site.def .
+The most likely candidates are
+.I site.def
+and the platform file, though, since those are the only ones you're supposed
+to edit.
+(If you're writing an
+.I Imakefile ,
+add that to the list, too.)
+Just remember that the effects of mistakes in the early files may
+not be manifest until much later on.
+Problems may appear to originate at locations far from the actual
+cause.
+.IP (1)
+.I Makefile
+trashing
+.IP
+A number of problems during ``make Makefile'' can result in a trashed
+.I Makefile .
+If you have
+.I xmkmf
+working, you can use that to regenerate the
+.I Makefile
+after fixing whatever the problem was.
+Otherwise you must recover it somehow.
+If you have a copy of
+.I Makefile
+stashed somewhere, you can use that.
+If not:
+the first thing that ``make Makefile'' does is to move the original
+.I Makefile
+to
+.I Makefile.bak ;
+if the new
+.I Makefile
+isn't created properly, you can
+usually recover it with ``cp Makefile.bak Makefile''.
+Then you can fix
+the problem and try again.
+If
+.I Makefile.bak
+is trashed as well, you can
+grab the
+.I Makefile
+from another directory at the same level and use that (this works because
+they both contain the same ``make Makefile''
+rule).
+You can also use a
+.I Makefile
+from a directory at another level,
+but you need to edit the line that sets TOP to reflect where the top
+project directory is in relation to the current directory.
+.IP
+Moral: make sure
+.I xmkmf
+is working first!
+.IP (2)
+Boolean vs. existent/nonexistent symbols
+.IP
+Some symbols are used in boolean fashion and are defined as
+YES or NO.
+They are tested by ``#if \fIsymbol\fR'' or ``#if !\fIsymbol\fR''.
+Others are turned on simply by being defined.
+They are tested by ``#ifdef \fIsymbol\fR'' or ``#ifndef \fIsymbol\fR''.
+Failure to distinquish the sense in which a symbol is used can lead to
+problems.
+It is necessary to define symbols properly
+.I and
+to test them properly.
+.IP
+.B Example:
+YES/NO symbols must be defined properly.
+SystemV is such a symbol, and the proper test is ``#if SystemV''.
+If you use ``#define SystemV'' instead of ``#define SystemV YES'',
+thinking that the former will turn it on, you'll
+have problems; ``#if SystemV'' turns into just ``#if'' and generates:
+.Ds .IP
+cpp: /usr/tmp/tmp-imake.\fImmm\fR:line \fInnn\fR: syntax error
+.De .IP
+.B Example:
+YES/NO symbols must be tested properly.
+If you test such a symbol with #ifdef, the test will always succeed,
+whether the value is YES or NO; the symbol is defined in
+.I both
+cases.
+.IP
+.B Example:
+Existent/nonexistent symbols must be tested properly.
+A symbol such as UseInstalled is simply defined (as nothing) or left undefined.
+If you say ``#define UseInstalled NO'', thinking that will turn it
+off, you will be surprised.
+(The test ``#ifdef UseInstalled'' will succeed.)
+.IP
+.B Example:
+Existent/nonexistent symbols must be properly.
+Such a symbol may be defined as nothing.
+If you test it, incorrectly, with ``#if symbol'', the test will fail.
+Use #ifdef.
+.IP (3)
+Rule definition problems
+.IP
+These can occur after ``make Makefile'', if a rule in
+.I Imake.rules
+is
+#define'd with a space between the rule name and the argument list:
+.Ds .IP
+#define rule(arglist) right
+#define rule (arglist) wrong!
+.De .IP
+.I cpp
+will define rulename as ``(arglist)''.
+When this happens, you'll see
+.Ds .IP
+make: line \fInnn\fR: syntax error
+.De .IP
+and you'll find `` (arglist)'' on line nnn of the
+.I Makefile
+because ``rule'' wasn't expanded properly (or at least not the way you
+expect).
+Fix it and try again.
+.IP
+Other similar errors can occur if rules are defined or used with spaces
+anywhere between the end of the macro name to the closing parenthesis of
+the argument list.
+This is particularly true if a macro argument is used
+to generate rule target names or file names.
+For example, AliasedLibaryTarget() looks like this:
+.Ds .IP
+.ta .5i +4i
+#define AliasedLibraryTarget(libname,alias) @@\e
+AllTarget(lib/**/alias.a) @@\e
+ @@\e
+lib/**/alias.a: lib/**/libname.a @@\e
+ $(RM) $@ @@\e
+ $(LN) lib/**/libname.a $@
+.De .IP
+If invoked as ``AliasedLibraryTarget(xyz, libxyz)'', this will
+expand to:
+.Ds .IP
+lib libxyz.a: libxyz.a
+ $(RM) $@
+ $(LN) libxyz.a $@
+.De .IP
+which won't do very well when
+.I make
+gets ahold of it.
+There will appear to be two targets (not one) having a dependency on
+.I libxyz.a \*-and
+one of them is itself!
+.IP (4)
+Failure to supply
+.I cpp
+symbol default values
+.IP
+When a
+.I make
+variable is equated to a
+.I cpp
+symbol, the
+.I cpp
+symbol must be defined somewhere, even if it's just
+defined as nothing.
+Otherwise the make variable will be set to the literal
+.I cpp
+symbol name.
+That is, if you have ``MAKEVAR=CppSymbol'', it must be preceded
+somewhere by:
+.Ds .IP
+#ifndef CppSymbol
+#define CppSymbol \fIwhatever\fR /* (``whatever'' might be empty) */
+#endif
+.De .IP
+or MAKEVAR will end up with the literal value ``CppSymbol''.
+.IP (5)
+Macro expansion failure
+.IP
+Suppose you include the following line in your
+.I Imakefile
+so that a special version of your library will be compiled:
+.Ds .IP
+DebuggedAndProfiledLibraryObjectrule()
+.De .IP
+After you regenerate
+.I Makefile ,
+you try to use it and get the message:
+.Ds .IP
+Make: Must be a separator on rules line \fInnn\fR. Stop.
+.De .IP
+This is symptomatic of a spelling error.
+If you look closely at the
+.I Imake.rules
+file, you'll find that the rule name is actually spelled
+``DebuggedAndProfiledLibraryObjectRule()''.
+If you don't spell a rule name correctly, it won't be expanded.
+Fortunately, these problems are easy to find, because at least the error
+message tells you where to look.
+Unfortunately, you can't say ``make Makefile'' after you fix
+.I Imakefile ,
+because the effect of the error is to make your
+.I Makefile
+unusable.
+Use
+.I xmkmf .
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/config-wrprc.ms b/web/glasgow/lit2x-0.16/mkworld/docs/config-wrprc.ms
new file mode 100644
index 0000000000..21f0036cfe
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/config-wrprc.ms
@@ -0,0 +1,691 @@
+.\" format with
+.\" xroff -ms % | lpr
+.\"
+.\" revision date - change whenever this file is edited
+.ds RD 24 July 1990
+.nr PO 1.2i \" page offset 1.2 inches
+.nr PD .7v \" inter-paragraph distance
+.\"
+.EH 'Multiple-project Imake'- % -''
+.OH ''- % -'Multiple-project Imake'
+.OF 'Revision date:\0\0\*(RD'\s+2\*-DRAFT\*-\s-2'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.EF 'Revision date:\0\0\*(RD'\s+2\*-DRAFT\*-\s-2'Printed:\0\0\n(dy \*(MO 19\n(yr'
+.\"
+.\" I - italic font (taken from -ms and changed)
+.de I
+.nr PQ \\n(.f
+.if t \&\\$3\\f2\\$1\\fP\&\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\c
+.if n .if \\n(.$>1 \&\\$2
+..
+.TL
+Using Imake for Multiple Projects
+.sp .5v
+(document version 1.02)
+.AU
+Paul DuBois
+dubois@primate.wisc.edu
+.AI
+Wisconsin Regional Primate Research Center
+Revision date:\0\0\*(RD
+.NH
+Introduction
+.LP
+.I imake
+is a tool for generating makefiles and is used to allow software projects
+to be configured easily on a wide variety of target machines.
+It is distributed with projects such as the X Window System and the Kerberos
+authentication system.
+The tool
+.I makedepend
+is typically used in conjunction with
+.I imake
+to generate dependencies in makefiles.
+.I xmkmf
+is also used, for bootstrapping makefiles from imakefiles.
+.LP
+This document describes the particular way
+.I imake
+is used to configure projects at WRPRC.
+The method is patterned after the way
+.I imake
+is employed in the X Window System (version 11, release 4).
+The X11R4 method is significantly more developed than in X11R3.
+Presumably,
+.I imake
+as used in Kerberos (currently at protocol revision 4)
+might have been used as a base, but I judged it
+unsuitable for two reasons: (i) I learned
+.I imake
+from studying X, so I'm probably imprinted to it;
+(ii) development of the configuration files in Kerberos appears to be
+at a more primitive level even than in X11R3.
+.LP
+The X11R4 approach allows configuration files to be stored either
+in a well-known system-wide location (e.g.,
+.I /usr/lib/config ),
+or in a
+.I config
+directory under the project top-level directory.
+.LP
+A more-than-passing acquaintance with
+.I imake
+is assumed here.
+Helpful companion documentation includes ``Configuration Management in
+the X Window System,'' the configuration and
+.I README
+files in the X11R4 distribution (in the
+.I mit/config
+directory), and the WRPRC configuration files (see below for
+information on distribution and availability).
+.NH
+Statement of Problem
+.LP
+Because of the flexibility
+.I imake
+provides as a
+configuration tool (once you figure out how to use it!),
+I had begun to use it on all my projects.
+Since these were all developed at the same site, the projects naturally
+had quite a bit of configuration information in common.
+On the other hand, different projects just as naturally had their own
+individual requirements.
+.LP
+What I had been doing was creating a
+.I config
+directory in each project directory, with a copy of the configuration files
+in each, modified as necessary for the project (otherwise known as ``using
+brute force'').
+I did not use configuration files in a system-wide location
+because of differing project requirements.
+At the same time, there was a great deal of redundancy between sets of
+configuration files since projects were built and installed
+in similar ways.
+It seemed rather wasteful and silly not to take advantage of this overlap,
+besides the fact that the multiple copies of files contributed to a
+maintenance inefficiency when changes were made that affected all projects.
+.LP
+This (unsatisfactory) situation prompts the question:
+how can the number of files to be maintained be minimized and how can
+configuration files be shared among projects without sacrificing the ability
+to specify project-specific information as necessary?
+.NH
+Solution to Problem
+.LP
+Since
+.I imake
+possessed the ability to look through multiple directories when looking
+for configuration files, the simplest solution to the problem seemed to be:
+.IP (i)
+Create a set of standard configuration files and store them in a well-known
+location (referred to here as StdConfigDir).
+.IP (ii)
+Allow projects to define an alternate configuration directory (referred to
+here as ProjConfigDir, typically the
+.I config
+directory under the project directory).
+.IP (iii)
+Tell
+.I imake
+to look through ProjConfigDir, then StdConfigDir for configuration files.
+This means changing
+.I xmkmf ,
+which executes
+.I imake ,
+and the configuration file definitions that construct
+.I imake
+commands.
+.LP
+In other words,
+a standard set of configuration files is created and stored in a well-known
+location for use by multiple projects.
+However, should it be required,
+individual projects place configuration files in their own
+.I config
+directory, which takes precedence over StdConfigDir when
+searching for files.
+In the degenerate case, projects need supply nothing if
+the standard stuff is sufficient; only files in StdConfigDir will be
+used.
+.NH
+Implementation of Solution
+.NH 2
+Imake.tmpl Architecture
+.LP
+The architecture of the
+.I imake
+template,
+.I Imake.tmpl ,
+as used in X11R4 is, roughly:
+.LP
+.DS
+.ta 3i
+header block section
+#include <\fIplatform\fR.cf> (platform-specific definitions)
+#include <site.def> (site-specific definitions)
+system description, build and installation definitions
+#include <Project.tmpl> (project-specific definitions)
+#include <Imake.rules> (\fIimake\fR rules)
+#include "./Imakefile" (\fIImakefile\fR for current directory)
+.DE
+.LP
+The header block section determines the machine type and the
+platform-specific file
+.I platform .cf
+to be included.
+.LP
+To accommodate other project-specific files, extra
+#include's are introduced into
+.I Imake.tmpl .
+The resulting modified architecture becomes:
+.LP
+.DS
+header block section
+.sp .2v
+#include <\fIplatform\fR.pcf>
+#include <\fIplatform\fR.cf>
+.sp .2v
+#include <site.pdef>
+#include <site.def>
+.sp .2v
+system description, build and installation definitions
+.sp .2v
+#include <Project.ptmpl>
+#include <Project.tmpl>
+.sp .2v
+#include <Imake.prules>
+#include <Imake.rules>
+.sp .2v
+#include "./Imakefile"
+.DE
+.LP
+The header block section now additionally determines the name of the
+project-specific platform file
+.I platform .pcf.
+.LP
+The modification is based on the notion of override files.
+Before any of the platform, site, project or rules
+files are included, another related file is
+included which may contain project-specific information.
+Standard versions of these project-specific files
+.I *.pcf , (
+.I site.pdef ,
+.I Project.ptmpl
+and
+.I Imake.prules )
+are present in
+StdConfigDir (to prevent file-inclusion errors) but they are all empty.
+If a given project has special configuration requirements, it may
+supply its own private versions of any of these files in its
+.I config
+directory.
+Since
+.I imake
+will search that directory before StdConfigDir, the standard (empty)
+versions will be overridden.
+The project does not have to actually replace them.
+.LP
+.B "Example 1:"
+At the one extreme, when a project has
+no special project-specific configuration requirements (no
+.I config
+directory, or an empty one),
+only the files in StdConfigDir are used to create makefiles.
+Since the default project-specific files are empty, the new
+architecture of
+.I Imake.tmpl
+is functionally equivalent to the old.
+At the other extreme, a project can replace
+.I all
+the configuration files; nothing from StdConfigDir is used then.
+.LP
+.B "Example 2:"
+The standard
+.I site.def
+file might be used by the system administrator to set the value of
+BinDir to the directory in which programs are installed.
+A project might want them installed somewhere else; this could be done
+by defining BinDir in the project-specific site file
+.I site.pdef
+to override the value in
+.I site.def .
+.LP
+.B "Example 3:"
+Override files may also be used to extend the standard configuration
+by defining symbols not appearing at all in the standard files.
+For instance, if some programs were to be installed in the standard
+BinDir, but others were to be installed in a private directory, a
+symbol such as ProjBinDir could be defined for the latter purpose in
+.I Project.ptmpl .
+.LP
+One bothersome thing about this architecture is the naming of
+.I Project.tmpl
+and
+.I Project.ptmpl .
+If
+.I Project.tmpl
+contains ``project-specific'' information, then what does
+.I Project.ptmpl
+contain?
+``Project-project-specific'' information?
+Ugh.
+I prefer to consider
+.I Project.tmpl
+to contain ``standard'' (i.e., best-guess) project configuration
+parameters, and
+.I Project.ptmpl
+to contain the parameters which actually are specific to a given project.
+.LP
+The disadvantages of this architecture are obvious:
+.IP \(bu
+.I Imake.tmpl
+is somewhat more complex.
+.IP \(bu
+StdConfigDir must be populated with the additional
+.I *.pcf ,
+.I site.pdef ,
+.I Project.ptmpl
+and
+.I Imake.prules
+files (although this is easy since they are all empty).
+.LP
+The advantages are:
+.IP \(bu
+Configuration information is centralized, but flexibility is maintained.
+Projects may
+override definitions in the the standard configuration files
+without replacing those files directly, and multiple projects may use
+files in StdConfigDir cooperatively without interfering with each other.
+.IP \(bu
+Override files minimize the need for individual
+projects to modify the standard non-project specific files
+.I Imake.tmpl , (
+.I *.cf ,
+.I site.def ,
+.I Project.tmpl
+and
+.I Imake.rules )
+directly.
+The philosophy underlying the architecture is that the standard files
+describe a common ``baseline'' configuration, and
+individual projects need specify configuration information (using
+private
+.I *.pcf ,
+.I site.pdef ,
+.I Project.ptmpl
+and
+.I Imake.prules
+files) only to the extent that they
+.I differ
+from the standard.
+.IP \(bu
+When improvements are made to the standard files, the changes are
+immediately available to any project using them via a normal
+configuration step, i.e., ``make Makefile;make Makefiles''.
+(Of course, it also becomes possible to break a lot of projects if an
+erroneous change is made.)
+.IP \(bu
+Overall, fewer files need to be maintained, and less space is used.
+.NH 2
+Other Changes
+.LP
+.I xmkmf
+is used to bootstrap makefiles from imakefiles.
+To accommodate the above scheme, it was
+modified from the version distributed with X11R4 to search the project's
+.I config
+directory, then the standard configuration directory
+(i.e., ProjConfigDir then StdConfigDir, not just StdConfigDir).
+.LP
+The definition of the makefile variable IMAKE_CMD in the configuration
+files was also changed:
+.LP
+.DS
+Old (from X11R4):
+#ifdef UseInstalled
+ IRULESRC = $(CONFIGDIR)
+ IMAKE_CMD = $(IMAKE) -DUseInstalled \e
+ -I$(IRULESRC) \e
+ $(IMAKE_DEFINES)
+#else
+ IRULESRC = $(CONFIGSRC)
+ IMAKE_CMD = $(NEWTOP)$(IMAKE) \e
+ -I$(NEWTOP)$(IRULESRC) \e
+ $(IMAKE_DEFINES)
+#endif
+.DE
+.\" allow page break here if necessary...
+.DS
+New:
+#ifdef UseInstalled
+ IMAKE_CMD = $(IMAKE) -DUseInstalled \e
+ -I$(NEWTOP)$(PROJCONFIGDIR) \e
+ -I$(STDCONFIGDIR) \e
+ $(IMAKE_DEFINES)
+#else
+ IMAKE_CMD = $(NEWTOP)$(IMAKE) \e
+ -I$(NEWTOP)$(PROJCONFIGDIR) \e
+ -I$(STDCONFIGDIR) \e
+ $(IMAKE_DEFINES)
+#endif
+.DE
+.LP
+The old rule determines whether to use versions of
+.I imake
+(and
+.I makedepend )
+already installed in public directories or
+build them in the source tree based on whether UseInstalled is defined or not.
+That symbol also determines where to look for configuration files and
+defines the value of IRULESRC accordingly.
+If UseInstalled is undefined, searches look in CONFIGSRC, the project's
+.I config
+directory, otherwise in CONFIGDIR, the standard configuration directory.
+.LP
+This behavior is unsuitable for the purposes described here, since both of
+those directories should be searched, if they exist.
+The new rule makes UseInstalled relevant only for determining where
+to find (and possibly build)
+.I imake
+and
+.I makedepend ,
+not where to look for configuration files.
+.NH
+Test of Implementation
+.LP
+After making the changes described above, a flight test was arranged.
+Nine projects developed under six different logins were converted to use
+the standard files.
+Projects supplied override files where necessary.
+These projects were all initially developed using configuration files
+that bore a
+fairly strong relationship to the standard set, so it was expected
+that conversion would not be unbearably odious.
+The degree of relationship broke down as follows:
+.IP \(bu
+Two projects used configuration files that were identical (or nearly
+so) to the standards.
+Each of these projects, unlike the other seven, comprised only a
+single source directory.
+As expected, conversion was completely trivial, once the top-level
+.I Makefile
+was rebuilt with
+.I xmkmf .
+.IP \(bu
+Four projects required additional project-specific specification
+beyond the standard configuration
+(special include file directories, link libraries,
+installation directories, etc.).
+These usually required only
+.I site.pdef
+and
+.I Project.tmpl
+files in their local
+.I config
+directories.
+One project required a
+.I platform.pcf
+file.
+Project owner and group names (used for install operations) were moved
+out of
+.I site.def
+files into
+.I site.pdef .
+.IP \(bu
+Three projects diverged from the standard files fairly significantly,
+because although their configuration files were initially set up from
+files similar to the standards, less effort had been exerted to keep
+them in sync as project development progressed.
+Besides the changes made to the projects described in the previous
+paragraph, there were additional special commands for compilation, special
+.I Imakefile
+rules, etc.
+Nevertheless, conversion proceeded smoothly and without incident.
+.LP
+One thing I had done in the original
+.I Project.tmpl
+files was to define certain
+makefile variables directly (e.g., ``INCLUDESRC=$(TOP)/h''), rather
+than by using a previously #define'd
+.I cpp
+symbol (e.g., ``INCLUDESRC=IncludeSrc'', where IncludeSrc is #define'd
+within a #ifndef/#endif block).
+This was a short-cut, that works in a non-shared environment but
+needed to be fixed to work in a shared environment.
+A default value of IncludeSrc needs to be placed in
+.I Project.tmpl ,
+and individual projects redefine that symbol as necessary in
+.I Project.ptmpl .
+.LP
+It was necessary to place a number of
+.I cpp
+symbol definitions in
+.I Project.tmpl
+within #ifndef/#endif blocks, since they became liable to being
+overridden in
+.I Project.ptmpl .
+.LP
+In the top-level imakefiles for the multiple source directory
+projects, the ``make World'' rules had to be adjusted to account for
+whether UseInstalled is defined or not.
+If so, the build process does not need to try to build
+.I imake
+and
+.I makedepend
+in the project source tree.
+(That would be a mistake since the source for those programs would not
+necessarily be present.)
+.LP
+Overall, conversion was simple and straightforward.
+I judged the conversion odiousness coefficient acceptably low.
+.NH
+Another Problem\*-Project Groups
+.LP
+The mechanism described above allows a group of similarly-configured
+projects to share configuration files and selectively extend or
+override them as necessary.
+This provides a solution to the original problem (how to avoid
+maintaining multiple full sets of files while maintaining flexibility),
+but leads to another.
+Suppose that instead of a group of projects, there exist several
+groups of projects, such that projects within a group are similar, but
+differences between groups are quite large.
+This can happen, for instance, if projects designed and developed at one
+site under certain conventions are installed at another
+site where different conventions are used.
+.LP
+The difficulty here is that there are two sets of ``standard'' configuration
+files, and they cannot both be installed in the same well-known
+location.
+This problem can be overcome quite simply.
+Instead of using StdConfigDir as the single well-known location in which
+the standards are installed, define StdConfigPath to be that
+directory, and use it as the root of a set of
+subdirectories, each of which corresponds to a project group.
+Each group's standard configuration files are installed in the appropriate
+directory, and StdConfigDir for a given project group
+will be defined as that directory (e.g., StdConfigPath/\fIabc\fR for
+project \fIabc\fR).
+.LP
+To allow
+.I xmkmf
+to be used for bootstrapping,
+it was modified slightly again to select
+one of the subdirectories as the hardwired-in default, but allow
+another to be selected through a
+.B \-C
+option.
+For convenience, the argument following
+.B \-C
+may be absolute or relative.
+If absolute, it is used unchanged.
+If relative, StdConfigDir is prepended.
+.LP
+This modification makes
+.I xmkmf
+incompatible with the version distributed with X11R4, which is a
+problem for sites using that version.
+Assuming X configuration files are installed in
+.I /usr/lib/X11/config
+and the value of StdConfigPath is
+.I /usr/lib/config ,
+this incompatibility can be obviated as follows:
+.LP
+.DS
+mkdir /usr/lib/config
+cd /usr/lib/config
+ln -s /usr/lib/X11/config X11
+ln -s X11 default
+.DE
+.LP
+For sites without symbolic links, the files in
+.I /usr/lib/X11/config
+can be copied into
+.I /usr/lib/config/X11 ,
+and
+.I xmkmf
+can be hacked to use
+.I /usr/lib/config/X11
+instead of
+.I /usr/lib/config/default
+as the default.
+Ugly, but workable.
+(Also known as ``crude, but effective''.)
+.LP
+With these conventions,
+projects within groups can share redundant information, as before, and
+project groups can coexist peacefully.
+.LP
+The nine projects previously converted were tested against these
+additional modifications.
+They required only ``xmkmf;make Makefile;make Makefiles'' to properly
+reset the configuration information in the makefiles.
+.NH
+Distribution of Projects
+.LP
+The mechanism described in this document appears to solve
+the problem of reusing
+configuration files while allowing for extension and override within
+individual projects.
+However, when a project is packaged for distribution, it's very little
+use to include only those configuration files which are unique to the
+project, if the receiving site doesn't have the standard files.
+Several alternatives come to mind.
+.IP \(bu
+Provide the standards as a separate distribution, along with the
+sources to
+.I imake
+and
+.I makedepend .
+This is perhaps inconvenient for the receiver, as it is another
+distribution that needs to be retrieved.
+.IP \(bu
+Copy all the standard files into the project's
+.I config
+directory and distribute along with the project.
+One has to be careful when doing the copying not to destroy the
+project's override files,
+the resulting distribution size is larger, and
+distributing the standards is unnecessary if receiving site
+has them already.
+Also, it is not clear which files are actually unique to the project
+when this is done.
+.IP \(bu
+Keep the project's unique configuration files in
+.I config
+(where they are normally anyway), and copies of the standard files in
+.I config-std .
+If the receiver has the latter already, they can be jettisoned easily,
+otherwise installed in the project's StdConfigDir.
+.LP
+It is unclear whether any of these has any compelling advantage over
+the others.
+.NH
+Beginning New Projects
+.LP
+If a new project has special configuration requirements, a file
+.I README.{project-name}
+should be created in
+.I config
+explaining what they are.
+.NH 2
+Define UseInstalled, or Not?
+.LP
+If a project wants to use the installed versions of
+.I imake
+and
+.I makedepend ,
+the initial makefile should be created from the the imakefile by executing
+.I xmkmf
+with no arguments (or just
+.B \-C
+.I configdir )
+in the project top-level directory.
+This will cause -DUseInstalled to be passed to
+.I imake
+which will in turn cause the version of IMAKE_CMD that
+includes -DUseInstalled to be selected from the configuration files.
+Thus -DUseInstalled will propagate nicely through all future ``make Makefile''
+operations.
+.LP
+If
+.I imake
+and
+.I makedepend
+are to be built in the project source tree, UseInstalled should not be defined,
+and you must have the source under the project.
+.I imake
+source is in
+.I config
+and
+.I makedepend
+source is in
+.I util/makedepend
+or
+.I util/scripts ,
+depending on the definition of UseCCMakeDepend.
+Execute ``xmkmf \fB.\fR'' (note the \fB.\fR!) in the project top-level
+directory.
+This will run
+.I imake
+without -DUseInstalled, and the proper IMAKE_CMD in the config
+files will be selected.
+.LP
+One problematic aspect of
+.I xmkmf
+is that it really should always pass -DUseInstalled, since it assumes there
+is an installed version of
+.I imake
+anyway (it doesn't specify a path to it).
+But then the problem becomes how to turn UseInstalled off later?
+You can't run ``make Makefile'' because the version of IMAKE_CMD that
+uses -DUseInstalled has already been selected.
+.NH
+Distribution and Availability
+.LP
+The standard WRPRC configuration files are (or will be soon)
+available for anonymous
+.I ftp
+access in the
+.I ~ftp/pub/imake-stuff
+directory, in file
+.I config-WRPRC.shar.Z
+on host
+.I indri.primate.wisc.edu
+(Internet address 128.104.230.11).
+These files illustrate the concepts discussed in this document.
+.LP
+This distribution also includes parts of the X11R4
+.I mit/util
+source tree (where
+.I makedepend
+and
+.I xmkmf
+are found) as well as
+.I msub ,
+a locally-developed utility for yanking the values of
+variables directly from makefiles to produce target files from templates.
+.LP
+The X11R4 configuration files are in the same directory, in
+.I config-X11R4.shar.Z .
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/imake-moraes.tex b/web/glasgow/lit2x-0.16/mkworld/docs/imake-moraes.tex
new file mode 100644
index 0000000000..afcc96b846
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/imake-moraes.tex
@@ -0,0 +1,884 @@
+% Document type: LaTeX
+%
+% $Header: imake.tex,v 1.1 89/02/25 03:25:37 moraes Exp $
+%
+% Copyright 1986, Mark Moraes
+% May be freely used for non-commercial purposes provided acknowledgement
+% to the source is given.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%\documentstyle[fullpage,notes]{article}
+\documentstyle[fullpage]{article}
+%\documentstyle[dvidoc]{article}
+
+\title{An {\em Imake} tutorial}
+
+\author{Mark Moraes, Computer Systems Research Institute,\\
+University of Toronto\\
+moraes@csri.toronto.edu}
+\date {Revised \today}
+
+\begin{document}
+\maketitle
+
+{\em {\tt \$(TOP)} in the document refers to the top level directory
+of the X Windows source tree.}
+
+\section{Introduction} {\em Imake} is a tool for generating Makefiles
+\footnote{Familiarity with the {\em make} program and C preprocessor
+syntax is assumed in this document. Those unfamiliar with these are
+advised to read their system manuals for {\em make} and {\em cpp} and
+experiment with them} for large software distributions.
+
+{\em Imake} uses the C preprocessor on macro-makefiles (called {\em
+Imakefiles}) to generate Makefiles. It uses a predefined template file
+for default values and macros. The {\em imake} program is part of, and
+used by the X Windows System software distribution. (The following
+description uses fragments from the X Windows distribution as examples
+--- you might want to look at the files in {\tt
+\$(TOP)/config} for more detailed information. The source
+code for {\tt imake} is in {\tt \$(TOP)/util/imake}, and includes a {\tt
+sample.rules} file as well as a manual page)
+
+This document attempts to provide a working introduction to {\em
+imake}. In particular, it provides an annotated tour of some of the
+relevant files, and through some example {em Imakefiles}. For a more
+precise description of {\em imake}'s workings, see the manual page.
+
+\section{Why {\em Imake}}
+
+Makefiles have some limitations for large software distributions,
+distributed over multiple directories, viz.
+
+\begin{itemize}
+
+\item A single makefile doesn't handle multiple directories well,
+ which means that each directory needs a makefile. At that
+ point, to change a default value, for example the directory
+ where the binaries are to be installed, you have to change all
+ the makefiles.
+
+\item Typically, makefiles are used to achieve a limited set of
+ actions, like create a binary from a set of object files, or
+ generate a library from some object files, etc. These can be
+ encapsulated in rules that are slightly more complex that the
+ ones {\em make} supports (which are only suffix based)
+
+\item A production makefile which supports all the actions necessary
+ for a development environment, can get fairly long ---
+ typically, you want a {\em clean} target, an {\em install}
+ target, a {\em depend} target, and an {\em all} target.
+
+\item For a system that is ported to many different systems, there are
+ bound to be differences in the requirements of the systems,
+ that cannot be dealt with solely at the C source level. For
+ instance, some System V Unix \footnote{Unix is a trademark of
+ AT\&T} machines provide a BSD compatibility library which must
+ be linked in with {\tt -lbsd}, and BSD includes that must the
+ C compiler must be told about with a {\tt -I/usr/include/bsd
+ option}. Vanilla {\em make} allows no facilities for changes
+ like this, and you end up having multiple makefiles, with
+ suffixes to indicate the type of system being used.
+\end{itemize}
+
+\section{A simple example}
+For example, for a simple program, {\tt xcalc}, the Imakefile looks something
+like:
+
+\begin{quote}
+\begin{verbatim}
+ LOCAL_LIBRARIES = $(XLIB)
+ SYS_LIBRARIES = -lm
+ #ifdef MacIIArchitecture
+ DEFINES = -DIEEE
+ #endif /* MacIIArchitecture */
+ SRCS = xcalc.c sr.c
+ OBJS = xcalc.o sr.o
+
+ ComplexProgramTarget(xcalc)
+\end{verbatim}
+\end{quote}
+
+This will generate a Makefile which will contain an {\tt all} target,
+and an {\tt xcalc} target, both of which will result in the program
+{\tt xcalc} being compiled and linked. The Makefile will also contain
+an {\tt install} target, which will install the binaries in specified
+destination directories, an {\tt install.man} target, which will
+install the manual pages for the program, a {\tt clean} target, which
+will remove all compiler generated files, editor backup files, etc.,
+and a {\tt depend} target which will invoke the {\em makedepend}
+program to generate Makefile depenencies.
+
+It will also contain a {\tt Makefile} target, so you only need to type
+{\tt make Makefile} to regenerate the Makefile should the Imakefile
+change.
+
+The real work lies in {\tt ComplexProgramTarget}, which is defined in
+the template as a {\tt \#define} macro, which expands out to the make
+rules needed to generate program {\em xcalc}, from the variables {\tt
+SRCS} and {\tt OBJS}. Let's take a look at that particular rule.
+
+\begin{quote}
+\begin{verbatim}
+/*
+ * This target is the general interface for building a single program
+ */
+#define ComplexProgramTarget(program) @@\
+ PROGRAM = program @@\
+ @@\
+AllTarget(program) @@\
+ @@\
+program: $(OBJS) $(LOCAL_LIBRARIES) @@\
+ $(RM) $@ @@\
+ $(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES) @@\
+ @@\
+relink:: @@\
+ $(RM) $(PROGRAM) @@\
+ $(MAKE) $(MFLAGS) $(PROGRAM) @@\
+ @@\
+InstallProgram(program,$(BINDIR)) @@\
+InstallManPage(program,$(MANDIR)) @@\
+DependTarget() @@\
+clean:: @@\
+ $(RM) $(PROGRAM)
+\end{verbatim}
+\end{quote}
+
+Ignoring {\tt AllTarget()} for now, we see that {\tt program} is
+defined to depend on the {\tt OBJS}, and {\tt LOCAL\_LIBRARIES}, and to
+make it, the old version is removed (a precaution to save disk space,
+among other things), and then, {\tt program} is linked from {\tt OBJS},
+{\tt LOCAL\_LIBRARIES}, and {\tt SYSLAST\_LIBRARIES}. ({\tt LDFLAGS}
+are link flags)
+
+An additional target {\tt relink::} is also generated, which can be
+used if libraries change. {\tt InstallProgram} generates the the
+{\tt install::} target, which puts the program in {\tt BINDIR},
+{\tt InstallManPage} installs the manual page, {\tt DependTarget} generates
+the target for {\em make depend} which invokes a {\em makedepend}
+program to follow all {\tt \#includes} in the source. These macros are
+listed below --- they aren't very complex.
+
+\begin{quote}
+\begin{verbatim}
+/*
+ * Install a man page.
+ */
+#define InstallManPage(file,dest) @@\
+InstallManPageLong(file,dest,file)
+
+/*
+ * Install a program
+ */
+#define InstallProgram(program,dest) @@\
+install:: program @@\
+ $(INSTALL) -c $(INSTALLFLAGS) program dest
+
+
+/*
+ * This makes the depend target given OBJS.
+ */
+#define DependTarget() @@\
+depend:: $(DEPEND) @@\
+ @@\
+depend:: @@\
+ $(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS) @@\
+ @@\
+$(DEPEND): @@\
+ @echo "making $@"; \ @@\
+ cd $(DEPENDSRC); $(MAKE) @@\
+
+
+#define AllTarget(depends) @@\
+all:: depends
+\end{verbatim}
+\end{quote}
+
+Note the use of make variables like {\tt \$(INSTALL)} to describe
+programs that are used - this makes it possible to define these in the
+templates, and thus enhances portability.
+
+Also, note that the make targets use a conditional dependency branch
+with double colons (::) rather than the more common single colon (:).
+This allows multiple make targets.
+
+Based on all this, the Imakefile expands to the following Makefile:
+
+\begin{quote}
+\begin{verbatim}
+LOCAL_LIBRARIES = $(XLIB)
+ SYS_LIBRARIES = -lm
+
+ SRCS = xcalc.c sr.c
+ OBJS = xcalc.o sr.o
+
+ PROGRAM = xcalc
+
+all:: xcalc
+
+xcalc: $(OBJS) $(LOCAL_LIBRARIES)
+ $(RM) $@
+ $(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
+
+relink::
+ $(RM) $(PROGRAM)
+ $(MAKE) $(MFLAGS) $(PROGRAM)
+
+install:: xcalc
+ $(INSTALL) -c $(INSTALLFLAGS) xcalc $(BINDIR)
+
+install.man:: xcalc.man
+ $(INSTALL) -c $(INSTMANFLAGS) xcalc.man $(MANDIR)/xcalc.n
+
+depend:: $(DEPEND)
+
+depend::
+ $(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
+
+$(DEPEND):
+ @echo "making $@"; \
+ cd $(DEPENDSRC); $(MAKE)
+
+clean::
+ $(RM) $(PROGRAM)
+\end{verbatim}
+\end{quote}
+
+
+We've omitted a few standard definitions for {\tt CFLAGS, CC, DEPEND,
+INSTALL, RM, LDFLAGS} etc. These are installation and system
+dependent, and form part of the Imake template. They will precede the
+above text.
+
+\section{Generating the Makefile for the first time}
+
+Invoking {\em Imake} for the first time is a little complex because
+you have to tell it where to find the template, as well as define the
+top level directory. The simplest way to do it is to use the {\tt ximake}
+script that should have been installed along with the rest of
+{\tt X} and {\tt imake}. The invocation is simply
+\begin{quote}
+{\tt ximake}
+\end{quote}
+
+\section{The {\em Imake} template}
+
+For a more portable setup, it is possible to split the template file
+into the following components:
+\begin{itemize}
+\item the rules
+\item the system-dependent macros, which vary depending on the
+ specific architecture/operating-system combination, things
+ like the compiler name, flags.
+\item the site dependent variables --- where to install the
+ binaries, libraries etc.
+\end{itemize}
+
+For example the X distribution has an {\tt Imake.rules} file, which
+defines various rules like {\tt ComplexProgramTarget()}, system
+dependent files of the form {\em machinetype}{\tt .cf}, eg. {\tt
+sun.cf, ultrix.cf}, ..., and a site dependent variables file called
+{\tt site.def}. The template looks something like the following: (This
+is abbreviated to keep the flavour but omit much detail, deemed
+unnecessary for the purposes of this tutorial --- annotations in C
+style comments)
+
+\begin{quote}
+\begin{verbatim}
+#ifdef sun
+#define MacroIncludeFile "sun.cf"
+#define MacroFile sun.cf
+#undef sun
+#define SunArchitecture
+#endif /* sun */
+
+/*
+ * The macrofile sun.cf contains definitions specific to Sun
+ * machines --- examples from it are after this file
+ */
+/**/###########################################################################
+/**/# platform-specific configuration parameters - edit MacroFile to change
+#include MacroIncludeFile
+
+/**/###########################################################################
+/**/# site-specific configuration parameters - edit site.def to change
+#include "site.def"
+
+/*****************************************************************************
+ * *
+ * DEFAULT DEFINITONS *
+ * *
+ * The following section contains defaults for things that can be overridden *
+ * in the various .macros files and site.def. DO NOT EDIT! *
+ * *
+ ****************************************************************************/
+
+#ifndef SystemV
+#define SystemV NO /* need system 5 style */
+#endif
+#ifndef BuildServer
+#define BuildServer YES /* go ahead and build server */
+#endif
+#ifndef UnalignedReferencesAllowed
+#define UnalignedReferencesAllowed NO /* if arbitrary deref is okay */
+#endif
+#ifndef BourneShell /* to force shell in makefile */
+#define BourneShell /bin/sh
+#endif
+
+/*
+ * Lots and lots more variables that can be overridden in the site.def
+ * including:
+ */
+
+#ifndef DestDir
+#define DestDir /* as nothing */
+#endif
+#ifndef UsrLibDir
+#define UsrLibDir $(DESTDIR)/usr/lib
+#endif
+#ifndef BinDir
+#define BinDir $(DESTDIR)/usr/bin/X11
+#endif
+#ifndef IncDir
+#define IncDir $(DESTDIR)/usr/include/X11
+#endif
+#ifndef IncRoot
+#define IncRoot $(DESTDIR)/usr/include
+#endif
+#ifndef AdmDir
+#define AdmDir $(DESTDIR)/usr/adm
+#endif
+#ifndef LibDir
+#define LibDir $(USRLIBDIR)/X11
+#endif
+#ifndef LintlibDir
+#define LintlibDir $(USRLIBDIR)/lint
+#endif
+#ifndef FontDir
+#define FontDir $(LIBDIR)/fonts
+#endif
+
+/*
+ * This is followed by the actual definitions that will appear in the
+ * Makefile, again, the list is partial.
+ */
+/*
+ * This list must be reflected in the DIRS_TO_BUILD list in the top-level
+ * Makefile.
+ */
+ DESTDIR = DestDir /* root of install */
+ USRLIBDIR = UsrLibDir /* libraries */
+ BINDIR = BinDir /* programs */
+ INCDIR = IncDir /* header files */
+ INCROOT = IncRoot /* base for header files */
+ ADMDIR = AdmDir /* server log files */
+ LIBDIR = LibDir /* rgb, XErrorDB, etc. */
+ LINTLIBDIR = LintlibDir /* lint libraries */
+ FONTDIR = FontDir /* font directories */
+
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
+ LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
+ LDFLAGS = $(CDEBUGFLAGS) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
+ TOP = TOPDIR
+#ifdef CompileWithInstalled
+ EXTENSIONLIB = $(USRLIBDIR)/lib/libXext.a
+ XLIB = $(USRLIBDIR)/libX11.a
+ XMULIB = $(USRLIBDIR)/libXmu.a
+ OLDXLIB = $(USRLIBDIR)/liboldX.a
+ XTOOLLIB = $(USRLIBDIR)/libXt.a
+ XAWLIB = $(USRLIBDIR)/libXaw.a
+ INCLUDES = -I$(INCDIR) -I$(INCROOT)
+#else /* ! CompileWithInstalled */
+ EXTENSIONLIB = $(EXTENSIONSRC)/lib/libXext.a
+ XLIB = $(XLIBSRC)/libX11.a
+ XMULIB = $(XMUSRC)/libXmu.a
+ OLDXLIB = $(OLDXLIBSRC)/liboldX.a
+ XTOOLLIB = $(TOOLKITSRC)/libXt.a
+ XAWLIB = $(AWIDGETSRC)/libXaw.a
+ INCLUDES = -I$(TOP)
+#endif /* CompileWithInstalled */
+
+/*
+ * The above fragment illustrates how different makefiles can be
+ * generated for the distribution, presumably, once with
+ * CompileWithInstalled not defined in site.def, so that the
+ * distribution can be bootstrapped and built for the first time, then
+ * with CompileWithInstalled defined in site.def so that it uses the
+ * already installed libraries instead of requiring the compiled
+ * objects remain forever in src directories
+ */
+
+ MACROFILE = MacroFile
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
+ $(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
+ IMAKE_DEFINES = /* leave blank, for command line use only */
+ IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
+ -s Makefile $(IMAKE_DEFINES)
+
+/*
+ * Now include the actual rules file --- this contains the definitions
+ * of macros like ComplexProgramTarget, as described earlier
+ */
+
+#include "Imake.rules"
+
+/*
+ * INCLUDE_IMAKEFILE is defined by the imake program to be the name of
+ * the Imakefile you are processing, usually just Imakefile. It
+ * gets included here.
+ */
+/**/###########################################################################
+/**/# start of Imakefile
+#include INCLUDE_IMAKEFILE
+
+/*
+ * Followed by some basic rules for all Makefiles, especially useful
+ * for Imakefiles where all you want to do is make the subdirectories.
+ */
+/**/###########################################################################
+/**/# Imake.tmpl common rules for all Makefiles - do not edit
+/*
+ * These need to be here so that rules in Imakefile occur first; the blank
+ * all is to make sure that an empty Imakefile doesn't default to make clean.
+ */
+emptyrule::
+
+CleanTarget()
+MakefileTarget()
+TagsTarget()
+
+#ifdef IHaveSubdirs
+
+/**/###########################################################################
+/**/# rules for building in SUBDIRS - do not edit
+
+InstallSubdirs($(SUBDIRS))
+InstallManSubdirs($(SUBDIRS))
+CleanSubdirs($(SUBDIRS))
+TagSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+
+#else
+
+/**/###########################################################################
+/**/# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install done"
+
+install.man::
+ @echo "install.man done"
+
+Makefiles::
+
+#endif /* if subdirectory rules are needed */
+
+/**/###########################################################################
+/**/# dependencies generated by makedepend
+\end{verbatim}
+\end{quote}
+
+The {\tt Sun.macros} file looks something
+
+\begin{quote}
+\begin{verbatim}
+#define SunOSPlatform YES /* set to NO if not running SunOS */
+#define OSName SunOS 3.5
+#define OSMajorVersion 3
+#define OSMinorVersion 5
+
+/**/# platform: $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
+/**/# operating system: OSName
+
+#if SunOSPlatform && OSMajorVersion == 3 && OSMinorVersion <= 2
+#define OptimizedCDebugFlags /* as nothing */
+#endif
+
+BOOTSTRAPCFLAGS =
+ AS = as
+ CC = cc
+ CPP = /lib/cpp
+ LD = ld
+ LINT = lint
+ INSTALL = install
+ TAGS = ctags
+ RM = rm -f
+ MV = mv
+ LN = ln -s
+ RANLIB = ranlib
+RANLIBINSTFLAGS = -t
+ AR = ar clq
+ LS = ls
+ LINTOPTS = -axz
+ LINTLIBFLAG = -C
+ MAKE = make
+STD_CPP_DEFINES =
+ STD_DEFINES =
+
+/* This defines the server you want */
+#define XsunServer Xsun
+\end{verbatim}
+\end{quote}
+
+There's more in the macros file but the rest of the definitions are X
+dependent.
+
+Most of the definitions shown here can be overridden in the {\tt
+site.def} file, so a system administrator can completely reconfigure
+the setup, if necessary.
+
+\section{Simple Imakefiles}
+
+We end with a few simple examples to illustrate the rules in the X
+Imake.rules.
+
+\subsection{A single program, one source file}
+
+The first is for a simple program that has only one source file {\tt
+xstring.c} and a corrsponding manual page {\tt xstring.man} It
+requires the libraries {\tt XAWLIB, XTOOLLIB, and XLIB} (the X Athena
+widgets, the X Toolkit, and the C library interface to X).
+
+\begin{quote}
+\begin{verbatim}
+LOCAL_LIBRARIES = $(XAWLIB) $(XTOOLLIB) $(XLIB)
+
+SimpleProgramTarget(xstring)
+\end{verbatim}
+\end{quote}
+
+\subsection{A single program, multiple source files}
+
+A slightly more complex Imakefile is the one for {\tt xcalc}, the
+example described earlier.
+
+\begin{quote}
+\begin{verbatim}
+LOCAL_LIBRARIES = $(XLIB)
+ SYS_LIBRARIES = -lm
+#ifdef MacIIArchitecture
+ DEFINES = -DIEEE
+#endif /* MacIIArchitecture */
+ SRCS = xcalc.c sr.c
+ OBJS = xcalc.o sr.o
+
+ComplexProgramTarget(xcalc)
+\end{verbatim}
+\end{quote}
+
+\subsection{Multiple programs}
+
+An Imakefile for a directory with multiple programs is a little more
+complicated. {\tt ComplexProgramTarget\_1} is similar to {\tt
+ComplexProgramTarget} but it uses {\tt OBJS1} to link the program
+instead of {\tt OBJS}. The first argument is the program name, the
+second is the list of {\tt LOCAL\_LIBRARIES}, and the third is the list of
+{\tt SYSLAST\_LIBRARIES}. It is possible to have more complex programs
+defined (the X Imake rules allow for 3 such targets) called
+{\tt ComplexProgramTarget\_1, ComplexProgramTarget\_2,} and {\tt
+ComplexProgramTarget\_3} which link {\tt OBJS1, OBJS2} and {\tt OBJS3}
+respectively.
+
+{\tt SingleProgramTarget} is a variant that allows multiple programs
+to be built - it differs from a {\tt ComplexProgramTarget\_}n in that
+it does not generate targets to install the program or the manual
+page, so it can be used for internal programs as well --- i.e.
+programs that are compiled to generate files or preprocess data for
+the installable targets.
+
+{\tt CFLAGS}, {\tt LINTFLAGS} and {\tt LDFLAGS} is defined as follows:
+\begin{quote}
+\begin{verbatim}
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
+ LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
+ LDFLAGS = $(CDEBUGFLAGS) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
+\end{verbatim}
+\end{quote}
+
+An Imakefile can redefine some of the right hand side variables -
+typically,
+\begin{itemize}
+\item {\tt CDEBUGFLAGS} can be {\tt -g} or {\tt -O}, or if you're
+using the GNU C compiler, {\tt -g -O},
+
+\item{\tt INCLUDES} is usually {\tt -I\$\{TOP\}} by default,
+
+\item {\tt DEFINES} is left for user defined {\tt-D} flags.
+({\tt STD\_DEFINES} is defined by the system macros file
+and should be left alone)
+
+\item {\tt SYS\_LIBRARIES} or {\tt SYSAUX\_LIBRARIES} can be used for
+{\tt -l} options to link in system libraries. ({\tt SYSLAST\_LIBRARIES}
+is defined by the system macros, typically for portability or
+emulation.
+
+\end{itemize}
+
+\begin{quote}
+\begin{verbatim}
+XWSRC=$(CONTRIBSRC)/widgets/Xhp
+XPICLIBDIR=$(LIBDIR)/xpic
+# The documents go in $(DOCDIR)/xpic - see the install target.
+DOCDIR=/local/doc/X11
+#############################################################
+# -DXPIC is used by the filename completion code.
+# -DMAGIC will include code that puts a '#! $(BINDIR)/xpic'
+# header on the saved xpic files, and make them executable, so
+# you can just execute the saved xpic file and it starts up
+# xpic.
+# -DDEBUG turns on debugging output - do you really want that?!
+# -DDRAWBBOX is also for debugging - it draws the bounding box
+# of all gels.
+# -DGRAB should be defined if XtAddGrab and XtRemoveGrab can be
+# made to work in Minibuf.c and input.c - I can't seem to get them
+# to work.
+# -DTYPEOUT includes the typeout code - this is still not used by
+# xpic - not much point defining it.
+DEFINES = -DXPIC -DMAGIC
+#############################################################
+CDEBUGFLAGS = -g
+INCLUDES = -I$(XWSRC) -Ibitmaps
+#############################################################
+# Note - You need the HP widgets (Xw) for the X11 Toolkit
+# These should be defined in an Imake.tmpl - except that the
+# normal Imake.tmpl insists on these being compiled in the
+# X directory tree.
+# For X11R3, the HP widgets use the R2 Intrinsics, which are
+# provided in with the HP src.
+XWLIB=$(XWSRC)/lib/libXw.a
+XTOOLLIB=$(XWSRC)/lib/libXt.a
+# Sigh - we use sin(), cos(), atan2() for arrow.
+MATHLIB=-lm
+
+OBJS1 = main.o windows.o xpic.o handlers.o input.o \
+ event.o grid.o error.o spline.o arrow.o newfonts.o \
+ util.o gels.o null.o obj_line.o obj_spline.o obj_text.o \
+ obj_box.o obj_circ.o obj_ell.o obj_block.o obj_elem.o \
+ updown.o text.o isqrt.o ask.o xtypeout.o Minibuf.o Window.o
+SRCS1 = main.c windows.c xpic.c handlers.c input.c \
+ event.c grid.c error.c spline.c arrow.c newfonts.c \
+ util.c gels.c null.c obj_line.c obj_spline.c obj_text.c \
+ obj_box.c obj_circ.c obj_ell.c obj_block.c obj_elem.c \
+ updown.c text.c isqrt.c ask.c xtypeout.c Minibuf.c Window.c
+#############################################################
+OBJS2 = x2pic.o hash.o
+SRCS2 = x2pic.c hash.c
+#############################################################
+OBJS3 = x2ps.o hash.o
+SRCS3 = x2ps.c hash.c
+
+PROGRAMS = xpic x2ps x2pic
+
+/*
+ * ComplexProgramTarget(program, local libraries, system libraries)
+ *
+ * The difference between local libraries and system libraries is that
+ * the program will depend on the local libraries, so they must be
+ * filenames, while the system libraries are not dependencies, so
+ * you can use -l
+ */
+ComplexProgramTarget_1(xpic,$(XWLIB) $(XTOOLLIB) $(XLIB),$(MATHLIB))
+
+/*
+ * SingleProgramTarget(program, objects, local libraries, system libraries)
+ *
+ * Note that this does not generate install: targets so we do that
+ * explicitly
+ */
+SingleProgramTarget(x2pic,$(OBJS2) $(MALLOC),,)
+InstallProgram(x2ps, $(BINDIR))
+InstallManPage(x2ps, $(MANDIR))
+
+SingleProgramTarget(x2ps,$(OBJS3) $(MALLOC),,$(MATHLIB))
+InstallProgram(x2pic, $(BINDIR))
+InstallManPage(x2pic, $(MANDIR))
+
+/*
+ * This will install the script x2tex.script as $(BINDIR)/x2tex
+ */
+InstallScript(x2tex, $(BINDIR))
+InstallManPage(x2tex, $(MANDIR))
+
+/*
+ * Some additional files we want to install. This is ordinary Make
+ * stuff, but we use Imake defined variables like $(INSTALL).
+ * $(INSTALLAPPFLAGS) is meant for normal text files.
+ */
+
+install::
+ -mkdir $(XPICLIBDIR)
+ $(INSTALL) $(INSTAPPFLAGS) x2ps.pro $(XPICLIBDIR)
+ $(INSTALL) $(INSTAPPFLAGS) x2ps.tra $(XPICLIBDIR)
+ -mkdir $(XPICLIBDIR)/fontdesc
+ $(INSTALL) $(INSTAPPFLAGS) fontdesc/xpic $(XPICLIBDIR)/fontdesc
+ $(INSTALL) $(INSTAPPFLAGS) fontdesc/x2pic $(XPICLIBDIR)/fontdesc
+ $(INSTALL) $(INSTAPPFLAGS) fontdesc/x2tpic $(XPICLIBDIR)/fontdesc
+ $(INSTALL) $(INSTAPPFLAGS) fontdesc/x2ps $(XPICLIBDIR)/fontdesc
+
+/*
+ * This is a trick that generates a .h file from the Makefile
+ * variables. We compare the newly generated file tune.h.new with
+ * the old one tune.h, and replace the old one with the new one only
+ * if it is different. This will prevent unnecessary compiles, and
+ * avoids the need to have .c files depend on the Makefile because
+ * you want them recompiled if a -D define changes
+ */
+tune.h: Makefile
+ echo \#define LIBDIR \"$(XPICLIBDIR)\" > tune.h.new
+ echo \#define PROGRAMNAME \"$(BINDIR)/xpic\" >> tune.h.new
+ echo \#define DUMPDIR \"$(DUMPDIR)\" >> tune.h.new
+ -cmp -s tune.h.new tune.h || cp tune.h.new tune.h
+\end{verbatim}
+\end{quote}
+
+\subsection{A library archive of object files}
+
+An Imakefile for a library looks something like:
+
+\begin{quote}
+\begin{verbatim}
+#
+# This library contains miscellaneous utility routines and is not part
+# of the Xlib standard.
+#
+
+ STD_DEFINES = LibraryDefines
+ CDEBUGFLAGS = LibraryCDebugFlags
+ INCLUDES = -I. -I$(TOP) -I$(TOP)/X11
+ INSTALLFLAGS = $(INSTINCFLAGS)
+ LINTLIBS = $(LINTXLIB)
+
+#ifdef OsNameDefines
+OS_NAME_DEFINES = OsNameDefines
+#endif
+
+HEADERS = \
+ Xmu.h
+
+SRCS = Atoms.c CrPixFBit.c CvtStdSel.c DefErrMsg.c DrRndRect.c FToCback.c \
+ Lookup.c Lower.c RdBitF.c StrToBS.c StrToBmap.c StrToCurs.c \
+ StrToJust.c StrToOrnt.c StrToWidg.c
+
+OBJS = Atoms.o CrPixFBit.o CvtStdSel.o DefErrMsg.o DrRndRect.o FToCback.o \
+ Lookup.o Lower.o RdBitF.o StrToBS.o StrToBmap.o StrToCurs.o \
+ StrToJust.o StrToOrnt.o StrToWidg.o
+
+all::
+
+NormalLibraryTarget(Xmu,$(OBJS))
+LintLibraryTarget(Xmu,$(SRCS))
+InstallLibrary(Xmu,$(USRLIBDIR))
+InstallLintLibrary(Xmu,$(LINTLIBDIR))
+
+InstallMultiple($(HEADERS),$(INCDIR))
+
+DependTarget()
+
+NormalLintTarget($(SRCS))
+
+\end{verbatim}
+\end{quote}
+
+Sometimes, it is nice to be able to generate libraries compiled with
+debugging on, and libraries compiled with profiling on, so that these
+can be used by developers. Something like the following, added before
+the {\tt NormalLibraryTarget}
+
+\begin{quote}
+\begin{verbatim}
+#if DebugLibXmu && ProfileLibXmu
+DebuggedAndProfiledLibraryObjectRule()
+#else
+# if DebugLibXmu
+DebuggedLibraryObjectRule()
+# else
+# if ProfileLibXmu
+ProfiledLibraryObjectRule()
+# else
+NormalLibraryObjectRule()
+# endif
+# endif
+#endif
+\end{verbatim}
+\end{quote}
+
+and something like the following added before the {\tt
+InstallMultiple} would do the trick quite nicely.
+
+\begin{quote}
+\begin{verbatim}
+#if ProfileLibXmu
+ProfiledLibraryTarget(Xmu,$(OBJS))
+InstallLibrary(Xmu_p,$(USRLIBDIR))
+#endif
+
+#if DebugLibXmu
+DebuggedLibraryTarget(Xmu,$(OBJS))
+#endif
+\end{verbatim}
+\end{quote}
+
+If we wanted a debugging library, we'd define the symbol {\tt
+DebugLibXmu} in the {\tt site.def} file, and the DebuggedLibraryRule
+would ensure it generated a library target for {\tt lib}name{\tt \_d.a},
+while if we defined the {\tt ProfileLibXmu} symbol, we would get a
+profiled library target for {\tt lib}name{\tt \_p.a}, in addition to
+the usual {\tt lib}name{\tt .a}. This sort of configurability is very
+hard to get from a vanilla makefile.
+
+\subsection{Subdirectories}
+
+The following Imakefile is for a directory that only contains
+subdirectories, and we want to make each of the subdirectories:
+
+\begin{quote}
+\begin{verbatim}
+#define IHaveSubdirs
+#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
+
+SUBDIRS = X \
+ oldX \
+ Xt \
+ Xmu \
+ Xaw
+
+MakeSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+MakeLintLibSubdirs($(SUBDIRS))
+MakeLintSubdirs($(SUBDIRS),install.ln,install.ln)
+
+\end{verbatim}
+\end{quote}
+
+This will have the {\tt Makefiles} target defined as well as {\tt
+Makefile} and using the {\tt make Makefiles} command will cause it to
+regenerate the Makefiles in the subdirectories. It does this by
+prepending a ``../'' in front of the {\tt TOP} variable, which
+means that {\tt TOP} should be a relative path. (This is the only
+reason for {\tt TOP} to be a relative path - if there are no
+subdirectories, {\tt TOP} can easily be an absolute path.
+
+\section{Miscellaneous}
+
+{\em Imake} puts null comments of the form {\tt \/\*\*\/} in front of
+normal {\em make} style comments i.e. the {\tt \#} to protect them
+from the C preprocessor. They survive unscathed in the resulting
+Makefile, while C style comments vanish. This provides a good way to
+distinguish betwen Imakefile comments and comments that you want to
+appear in the Makefile.
+
+However, it does not protect comments in the files that are included {\tt
+(site.def, Imake.rules, machine.macros)} so if you want to use {\tt
+\#} style comments in those files, you must protect them yourself with
+{\tt \/\*\*\/} in front of them.
+
+\section{History}
+
+{\em Imake} was originally written by Todd Brunhoff (toddb@tekcrl.crl)
+for X Windows Version 11 Release 1. The configurations for X Windows
+Version 11 Releases 2, 3 and 4 were reworked considerably by Jim Fulton
+(jim@expo.lcs.mit.edu) to isolate the rules, machine dependent
+information, and site dependent information into separate files.
+
+\end{document}
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/Jmakefile b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/Jmakefile
new file mode 100644
index 0000000000..21e70e9142
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/Jmakefile
@@ -0,0 +1,4 @@
+LitStuffNeededHere(docs depend)
+InfoStuffNeededHere(docs)
+
+LitDocRootTarget(mkw_guide,lit)
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/mkw_guide.lit b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/mkw_guide.lit
new file mode 100644
index 0000000000..2de7bf5199
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_guide/mkw_guide.lit
@@ -0,0 +1,716 @@
+%
+% $Header$
+%
+\begin{onlystandalone}
+\documentstyle[11pt,literate]{article}
+\begin{document}
+\title{The ``make world'' configuration system---a guide for the brave}
+\author{The GRASP Team (scribe: Will Partain), \\
+Department of Computing Science, \\
+University of Glasgow, \\
+Glasgow, G12 8QQ, UK. \\
+\\
+Email: glasgow-haskell-\{bugs,request\}\@dcs.glasgow.ac.uk}
+\maketitle
+\begin{rawlatex}
+\tableofcontents
+\clearpage
+\end{rawlatex}
+\end{onlystandalone}
+
+%************************************************************************
+%* *
+\section[make-world-tutorial]{An introduction to the ``make world'' configuration subsystem}
+%* *
+%************************************************************************
+
+{\em [MEGA-NOTE: This subsystem needs SUBSTANTIAL REVISION; however,
+the required time hasn't sprung/isn't springing free. Also, there is
+no clear winner emerging in the How-to-Configure-Free-Software
+sweepstakes. (Ideas welcome.) This documentation is only intended as
+a ``survival guide'' in the interim.]}
+
+Our sources are manipulated with a variant of the ``imake'' system
+that comes with the X Window System.\footnote{Actually, our variant is
+a variant of Paul DuBois's ``imake for multiple projects,'' from the
+Wisconsin Regional Primate Research Center. We are grateful to him
+for making his work available to the world.} (We call our version of
+the main program ``jmake,'' so things don't get mixed up.) Our
+everyday term for the system is ``make world,'' because the system's
+mission is to (re-)build {\em everything} correctly when you type
+\tr{make world}.
+
+%************************************************************************
+%* *
+\subsection[make-world-goals]{Goals of ``make world''}
+%* *
+%************************************************************************
+
+The purpose of the ``make world'' subsystem is to help with these
+configuration tasks:
+\begin{itemize}
+\item
+Manipulating the system as a whole. We want to be able to do:
+\begin{verbatim}
+% cd ghc-<version>
+% make <target>
+\end{verbatim}
+
+and for the make \tr{<target>} to be built {\em throughout} the system
+(e.g., \tr{make depend}, to build all make dependencies in the
+distribution). The code to do this recursive make-ery must live in
+one place and must {\em not} rely on (zillions of) hand-built
+Makefiles to work.
+
+\item
+Porting the system to a new machine platform. All machine dependencies
+must be gathered together in one place and, again, must not be
+distributed through zillions of Makefiles (just waiting to go wrong).
+
+\item
+Customising the system for a particular site. Same rationale.
+
+\item
+Customising the \Haskell{} compilation system that you build. Example
+possibilities (not all relevant at this time): choosing one of several
+parsers, choosing which optimisation passes to build in, choosing to
+omit/include some debugging code, choosing which code generator(s) to
+build in, choosing which C compiler to use in compiling
+\Haskell{}-generated C files, what C compiler options to use in that
+case, and on and on....
+
+\item
+Customising the installation of the compilation system. Where the
+binaries go, where the library files go, ...
+
+\item
+Supporting several builds/customisations ongoing simultaneously.
+
+\item
+Supporting several people working from a master copy of the source.
+\end{itemize}
+
+%************************************************************************
+%* *
+\subsection[make-world-concepts]{Basic concepts of ``make world''}
+%* *
+%************************************************************************
+
+The ``make world'' subsystem builds an ordinary \tr{Makefile} for each
+directory in a system, from a set of system-wide configuration files
+(in the \tr{mkworld/} directory) and a single directory-specific file,
+called the \tr{Jmakefile}. Things the ``make world'' system needs to know
+from you:
+\begin{description}
+\item[Machine architecture of the host you're building with:]
+It normally figures this out for itself.
+
+\item[What project you're configuring for:] For the new Glasgow
+Haskell compiler, use \tr{ghc}.
+
+\item[What setup of the project you're configuring for:] Unless you
+have reason to do otherwise, use the \tr{std} setup.
+
+\item[The absolute pathname of the top of the source tree.]
+\end{description}
+
+Armed with this information, the ``make world'' system will create
+\tr{Makefiles} in all the subdirectories of a system. Each of the
+Makefiles will be, in effect, a {\em database of configuration facts}.
+Obviously, the program \tr{make} can then use these facts. You can
+also use the utility program \tr{msub} to substitute these facts into
+other source files.
+
+%************************************************************************
+%* *
+\subsection[make-world-operation]{Basic operation of ``make world''}
+%* *
+%************************************************************************
+
+Just like its ``imake'' ancestor for the X Window System, ``make
+world'' is a {\em low-tech} solution to the tasks mentioned above.
+The files involved are:
+\begin{description}
+\item[Platform-, site-, project-, and setup-dependent configuration files:]
+{\em All} such information lives in {\em one} directory, notably the
+top-level \tr{mkworld} directory.
+
+\item[Configuration file for a particular directory:]
+This is what the one-per-directory \tr{Jmakefile}s are.
+\end{description}
+
+All of the above files are a mixture of \tr{cpp} (C pre-processor)
+directives and plain-vanilla make stuff (very plain vanilla---so it
+will work with any make). The \tr{jmake} program simply feeds the
+master template file (\tr{mkworld/Jmake.tmpl}) into \tr{cpp}, which
+will then \tr{#include} all of the appropriate platform-, site-,
+etc., dependent files, as well as the \tr{Jmakefile} for the directory
+in question. \tr{cpp} expands all of the \tr{#define}d macros, and
+what you are left with is an ordinary (but large and confusing)
+\tr{Makefile}!
+
+Here is a small, possibly instructive example, from the \tr{Jmakefile}
+for this document:
+\begin{verbatim}
+INeedLitStuffHere(all depend)
+
+LitDocRootTargetWithNamedOutput(root,lit,root-standalone)
+\end{verbatim}
+
+The exact meanings of these \tr{cpp} macro-invocations are not
+important;\footnote{They say that (1)~the literate stuff must be available
+before doing \tr{make all} or \tr{make depend}, and (2)~we want to
+build a literate document with provision for both standalone
+processing and otherwise.} what is important is what you {\em don't}
+see: hard-wired filenames about where to find the literate programs or
+other tools, hardwired install directories, presuppositions about how
+your man pages are arranged, what kind of hardware you have,
+idiosyncratic (and probably inappropriate) \tr{make} suffix rules,
+etc., etc.
+
+After expanding the master \tr{Jmake.tmpl} template with all of the
+appropriate configuration files in \tr{mkworld/}, the above fragment
+blows out into (in the real \tr{Makefile}):\footnote{Some long lines
+truncated.}
+\begin{verbatim}
+all depend:: $(INFO) $(MAKEINFO) $(POSTMAKEINFO)
+
+$(INFO) $(MAKEINFO) $(POSTMAKEINFO):
+ @echo "checking $@ over in" $(INFOSRC) "first..."; \
+ cd $(INFOSRC); $(MAKE) all; \
+ echo "okay, continuing in $(CURRENT_DIR)"
+
+all depend:: $(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex [...]
+
+$(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex [...]
+ @(cd $(LITSRC); if [ -f lit2pgm ]; then \
+ echo "checking $@ in $(LITSRC) first..."; $(MAKE) all; else \
+ echo "bootstrapping $@ with lit2pgm.BOOT in $(LITSRC) first..."; \
+ $(MAKE) LIT2PGM="lit2pgm.BOOT -Alit2pgm" lit-deatify all; fi; \
+ echo "okay, continuing in $(CURRENT_DIR)")
+
+docs:: root.info root.dvi
+
+clean::
+ $(RM) root.info root.dvi root.texi root.tex
+
+depend::
+ $(MKDEPENDLIT) $(MKDEPENDLITFLAGS) root.lit
+
+root.info:: root.texi
+ $(RM) $@
+ $(MAKEINFO) $(MAKEINFOFLAGS) root.texi \
+ && $(POSTMAKEINFO) root.info
+
+root.dvi:: root.tex
+ $(RM) $@
+ $(LTX) root.tex
+
+root.texi: root-standalone.itxi
+ $(RM) $@
+ $(LIT2TEXI) -S $(LIT2TEXIFLAGS) -N root.info -o root.texi root-standalone.itxi
+
+root-standalone.itxi: root.lit
+ $(RM) $@
+ $(LIT2TEXI) -S -c $(LIT2TEXIFLAGS) -o root-standalone.itxi root.lit
+
+root.tex: root-standalone.itex
+ $(RM) $@
+ $(LIT2LATEX) -S $(LIT2LATEXFLAGS) -o root.tex root-standalone.itex
+
+root-standalone.itex: root.lit
+ $(RM) $@
+ $(LIT2LATEX) -S -c $(LIT2LATEXFLAGS) -o root-standalone.itex root.lit
+\end{verbatim}
+
+%************************************************************************
+%* *
+\subsection[make-world-more-info]{More information about Imake (``make world'' ancestor)}
+%* *
+%************************************************************************
+
+{\em As I say, the ``make world'' system is a clear candidate for
+revision, so we aren't over-exerting ourselves to make this version
+better.}
+
+I got the ``imake'' code that I turned into ``jmake'' (a.k.a. ``make
+world'') from Paul DuBois, at the Wisconsin Regional Primate Research
+Center. The principles of operation are {\em exactly} the same, so I
+have put a copy of every known ``imake'' document in the
+\tr{mkworld/doc/} subdirectory.
+
+%************************************************************************
+%* *
+\subsection[config-file-org]{Organisation of the \tr{mkworld} configuration files}
+%* *
+%************************************************************************
+
+The main Makefile template in \tr{mkworld/} is \tr{Jmake.tmpl}. It
+first determines the machine type, then starts slurping these files
+(all in \pl{mkworld/}) in this order (assume project \tr{project} and
+setup \tr{setup}):
+\begin{verbatim}
+# find out things about the machine
+<a platform-specific file>
+
+# now things about your site
+site-project-setup.odef
+site-project.odef
+site.def
+
+# things all projects can use but that your project/setup might override
+AllProjects-project-setup.otmpl
+AllProjects-project.otmpl
+AllProjects.tmpl
+
+# things just for your project
+Project-project-setup.otmpl
+Project-project.tmpl
+
+# the rules, or macro definitions, actually used in Jmakefiles
+# (may be overidden [uncommon])
+Jmake-project-setup.orules
+Jmake-project.orules
+Jmake.rules
+
+# finally, the directory-specific what-you-want-to-happen info
+Jmakefile
+\end{verbatim}
+
+Notice how you can always use a \tr{*-project-setup.*} file to
+override a \tr{*-project.*} file, which you can use to override the
+general defaults...
+
+%************************************************************************
+%* *
+\subsection[std-make-world-actions]{Standard actions in ``make world''}
+%* *
+%************************************************************************
+
+The expected normal cycle of \tr{make}ing with a ``make world''-ified
+project (once you're sure all your configuration files are set up
+correctly!):
+\begin{description}
+\item[\tr{make Makefile}:]
+Make the very topmost Makefile. It's crucial to get this right!
+\item[\tr{make Makefiles}:]
+Make all the other Makefiles (recursively).
+\item[\tr{make depend}:]
+Make all the automatically-generated dependencies (with
+\tr{mkdependHS}, \tr{mkdependC}, \tr{mkdependlit} etc.).
+\item[\tr{make all}:]
+Build the system(s).
+\item[\tr{make tags}:]
+Make some Emacs-friendly TAGS files, if you believe in them.
+\item[\tr{make runtests}:]
+Run any test suite that you may have provided.
+\item[\tr{make docs}:]
+Make any documentation that goes with the system(s).
+\item[\tr{make install}:]
+Install the system(s).
+\item[\tr{make install_docs}:]
+Install the documentation.
+\item[\tr{make clean}:]
+Clean up after yourself.
+\item[\tr{make veryclean}:]
+If you really want to get rid of all machine-generated files...
+\end{description}
+
+Another generally-supported make target is: \tr{make whoami} (echos
+the project and setup strings).
+
+%************************************************************************
+%* *
+\subsection[when-to-make-what]{When to use what \tr{make} target}
+%* *
+%************************************************************************
+
+Several of the standard ``make world'' targets depend upon you to
+re-run them at the right time.
+
+\begin{itemize}
+\item
+The normal thing you do 90\% of the time is just type:
+\tr{make} (or, equivalently, \tr{make all}).
+
+\item
+If you change a \tr{Jmakefile} (or the configuration files in the
+\tr{mkworld/} directory), then you need to re-\tr{make Makefile}.
+
+\item
+If you changed the configuration files in some globally-important way,
+then you should re-\tr{make Makefiles}, {\em after} the
+\tr{make Makefile}.
+
+\item
+If you change anything from which make dependencies are automatically
+generated (e.g., import declarations in \Haskell{} modules or
+\tr{#include} directive in C programs), then you need to
+re-\tr{make depend} before continuing with a regular \tr{make}.
+\end{itemize}
+
+Rather than worry too much about these constraints, we re-run these
+things every night:
+\begin{verbatim}
+% (make Makefile && make Makefiles && make depend) >& overnight.log
+\end{verbatim}
+
+%************************************************************************
+%* *
+\section[day-to-day-make-worlding]{Day-to-day use of ``make world'' (valuable tips!)}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsection[bad-Makefile]{When you mess up your \tr{Makefile}}
+%* *
+%************************************************************************
+
+The NUMBER ONE \tr{make}ing RULE: If, in running \tr{make Makefile} or
+\tr{make depend} or {\em anything}, you get a message indicating your
+\tr{Makefile} is rubbish, {\em immediately} (a)~save a copy to look
+at, and (b)~restore a viable \tr{Makefile} with:
+\begin{verbatim}
+mv Makefile.bak Makefile
+\end{verbatim}
+That way, at least you will have a working (if out-of-date)
+\tr{Makefile} while you consider your options!
+
+%************************************************************************
+%* *
+\subsection[new-dir-in-mkworld]{Adding a directory to a ``make world'' source tree}
+%* *
+%************************************************************************
+
+\begin{verbatim}
+% mkdir new_dir
+
+% emacs ./Jmakefile
+ # Add "new_dir" to the list of SUBDIRS (in parent directory).
+
+% emacs new_dir/Jmakefile
+ # Create a Jmakefile for the new subdir; probably copy one from elsewhere.
+ # An empty Jmakefile works, and is sometimes useful.
+
+% make Makefile
+ # Tells current-directory's Makefile that it has a new subdirectory.
+
+% make SUBDIRS=new_dir Makefiles
+ # makes the Makefile (from the new Jmakefile) in "new_dir"
+\end{verbatim}
+
+%************************************************************************
+%* *
+\subsection[feeding-flags-with-mkworld]{Feeding command flags into ``make world''}
+%* *
+%************************************************************************
+
+NOT DONE YET.
+
+%************************************************************************
+%* *
+\subsection[overnight-mkworlding]{Nice ``mkworld'' things to do overnight}
+%* *
+%************************************************************************
+
+Out-of-sync ``make world'' stuff spells eventual trouble. What we do
+every night (at a minimum) is:
+\begin{verbatim}
+% cd top-of-your-world
+% make Makefile
+% make Makefiles
+% make depend
+% make all
+\end{verbatim}
+
+%************************************************************************
+%* *
+\subsection[fastmake-script]{Using the \tr{fastmake} script (to cheat)}
+%* *
+%************************************************************************
+
+One rather great pain about the make-dependencies generated by
+\tr{makedependHS} for the compiler is that there are zillions of them,
+and quite innocuous changes to the source modules can spawn {\em
+massive} recompilation. If you keep your wits about you, judicious
+use of the \tr{fastmake} script (provided in \tr{utils/scripts}) can
+help a lot.
+
+Typing \tr{fastmake -help} gets you the documentation for the script;
+it also describes the only two uses that I would recommended:
+(1)~Recompiling when interfaces are known to be stable [very common], and
+(2)~Compiling a module that's just had functions {\em added} then
+tweaking the \tr{.hi} file's timestamp so the change ``doesn't show''.
+
+%************************************************************************
+%* *
+\subsection[using-sun4s-and-sun3s]{Using both Sun4s and Sun3s to compile}
+%* *
+%************************************************************************
+
+[This is happily irrelevant in a Sun4-only compiling-with-HBC world.
+It is most useful if compiling-for-Sun3s (prototype Glasgow compiler),
+but you'd really rather use a Sun4 to do it [to go faster].]
+
+It is a pain to build the compilation system for Sun3s,
+even though most of us have Sun4s. This is really only a
+problem for the compiler proper (\tr{compiler/hsc}). Here's what we
+do. (We assume you have a copy of the Sun4-to-Sun3 version of the
+prototype compiler.)
+
+The basic idea, after doing \tr{cd compiler}, is to do \tr{(l|fast)make asms}
+on a Sun4 (to make all the \tr{.s} assembler files) and then finish
+the job on a Sun3 with \tr{make hsc} (or \tr{make all}).
+
+The problem is that the rest of the distribution has been built for a
+Sun3, so when \tr{make} reaches out to run some other part of the
+distribution (e.g., \tr{lit-deatify}, run by \tr{lit2pgm}), you'll be
+trying to run a Sun3 binary on a Sun4. No go.
+
+There are two solutions. Both depend on {\em installing} at least the
+literate-programming stuff, and perhaps the ``make world'' stuff, too.
+(\tr{cd} to those subdirectories, and see if \tr{make install} does
+what you want.)
+
+The first solution is to use the \tr{lmake} script, provided in
+\tr{utils/scripts/lmake.sh}, when you are compiling with a Sun4.
+This trivial script merely overrides \tr{make}'s default ideas about
+where to find some programs.
+
+The second solution is to reconfigure your whole system to use
+``installed utilities,'' a mysterious and murky `feature' of the
+make-world system. Cd to the root directory of your source tree and
+proceed just as described in the installation document,
+with {\em one change}: Instead of the magic line:
+\begin{verbatim}
+make -f Makefile.BOOT BOOT_DEFINES="-P ghc -S std -DTopDirPwd=/h/me/ghc-0.06"
+\end{verbatim}
+
+use this other even more magic line:
+
+\begin{verbatim}
+mkworld/jmkmf -P ghc -S std -DTopDirPwd=/h/me/ghc-0.06
+\end{verbatim}
+Then \tr{make Makefiles}, \tr{make depend}, etc., as before. After
+all this, you should be able to \tr{make asms} on either a Sun3 or
+Sun4, without problems.
+
+%************************************************************************
+%* *
+\section[sharing-w-link-trees]{Sharing source code using symbolic-link trees}
+%* *
+%************************************************************************
+
+If you want to build the system for several architectures, setups, or
+whatever, but not duplicate the sources, you can make a {\em link tree}
+of the distribution---that is, a ``clone'' of the distribution
+directory structure but with each file represented by a symbolic link
+to the real source file.
+
+If you make changes to the real source file, then you simply have to
+re-\tr{make} in the link tree to rebuild for that arch/setup.
+Contrariwise, things that happen in the link tree should not affect
+the master sources.
+
+This is what we do at Glasgow, where several people are hacking on
+bits of the compiler at any given time. These notes were written
+mainly to help us remember what we did last time!
+
+%************************************************************************
+%* *
+\subsection[link-tree-principles]{The objectives of working this way}
+%* *
+%************************************************************************
+
+What we want to have on our disks:
+\begin{enumerate}
+\item
+A single common more-or-less-stable source tree that everyone can
+share (assumed to be about a half dozen people). ``Read-only.''
+
+\item
+A handful of common ``builds'' of the common source for various
+machines, which people can share. These ``build trees'', also
+``read-only,'' link into the common source tree (above).
+
+Out of the whole distribution, one person is likely to be interested
+in a tiny part of it. There is no reason they should have a full set
+of object files (which is probably huge). By linking into a common
+build tree, all those objects can be shared.
+
+\item
+Separate link trees for individuals, that they can play with and use
+to prepare wadges of ``stable code'' --- to be fed back into the
+``common source tree'' periodically.
+\end{enumerate}
+
+What we want to do with them:
+
+%************************************************************************
+%* *
+\subsection[basic-link-trees]{Creating link trees of object files for everyone to share}
+%* *
+%************************************************************************
+
+Let's assume that the basic source tree is in \tr{~grasp/ghc}.
+
+Now, if everyone simply links to this and \tr{makes} thereafter, each
+link tree will end up with a full set of objects, most of which will
+be of no interest to the link-tree owner.
+
+So, we do a basic build for each architecture, and then link {\em into
+those object-full trees}! Here goes:
+\begin{verbatim}
+% mkdir ghc-full-hbc-sun4 # full setup, compile w/ hbc, for sun4
+% cd ghc-full-hbc-sun4
+% lndir ~grasp/ghc # make the links
+
+% make -f Makefile.BOOT BOOT_DEFINES="-P ghc -S full -DTopDirPwd=/users/fp/grasp/ghc-full-hbc-sun4"
+\end{verbatim}
+
+%************************************************************************
+%* *
+\subsection[create-link-tree]{Creating a link-tree version of the compiler}
+%* *
+%************************************************************************
+
+Suppose the source is in \tr{~grasp/ghc}. We want to make a link tree
+called \tr{./ghc-sun4}, which will be used to do a build for Sun4s.
+Here's how to set up the basic structure:
+\begin{verbatim}
+% mkdir ghc-fred
+% cd ghc-fred
+% lndir ~grasp/ghc
+\end{verbatim}
+
+If you wish to be a bit tidier:
+\begin{verbatim}
+% cd ghc-fred
+% zap-junk-links
+\end{verbatim}
+
+Now fiddle the configuration stuff, as described in the installation
+document. make your Makefiles and dependencies, ..., also as
+described there. It will be something like:
+\begin{verbatim}
+% make -f Makefile.BOOT BOOT_DEFINES="-P ghc -S fred-setup -DTopDirPwd=/u/h/ghc-fred"
+\end{verbatim}
+
+ToDo: we need to provide emacs-ery to ensure copying works right.
+
+We often build not-quite-full link trees: usually just a link tree of
+the \tr{compiler/} directory. See the example not too far below
+about building a new setup.
+
+%************************************************************************
+%* *
+\subsection[chopping-down-link-trees]{Finding the good stuff in a link tree}
+%* *
+%************************************************************************
+
+(NOT TESTED RECENTLY.)
+
+Suppose, as in the previous section, you had a link tree
+\tr{./ghc-sun4}, linked to \tr{~grasp/ghc}. Suppose that, for some
+reason, you have made changes in the \tr{./ghc-sun4} tree, and you
+want to find those changes, so that they might be applied to the
+(presumably) master source in \tr{~grasp/ghc}.
+\begin{verbatim}
+make veryclean
+# remove the links
+find . -type l -print | xargs rm
+# remove the generated Makefiles
+find . -name Makefile -print | xargs rm
+# rm the generated .prl files and lit2stuff in ./literate ???
+# take the diffs
+diff -rc2 ~grasp/ghc .
+# Remove the fluff from the diffs, mangle, etc., etc.
+# Watch particularly for files that exist _only_ in ghc-sun4!
+# ...
+# now apply them if you wish
+cd ~grasp/ghc
+patch -p0 < <the-diffs-file>
+\end{verbatim}
+
+%************************************************************************
+%* *
+\subsection[new-setup]{Building a new setup (configuration) of the system}
+%* *
+%************************************************************************
+
+NOT DONE YET. (Not expected to be hard.)
+
+This is what I did when I created a special setup for trying to
+bootstrap the compiler (compile it with itself).
+
+First, I created a directory for it:
+\begin{verbatim}
+% mkdir ~grasp/ghc-boot
+\end{verbatim}
+
+I then made symbolic links to the master copy of all parts of the
+compilation, except the compiler itself. There, I made a whole
+symlink-tree.
+\begin{verbatim}
+% cd ~grasp/ghc-boot
+% ln -s ~grasp/ghc/* .
+% rm compiler # put in a real directory for this one piece
+% mkdir compiler
+
+% cd compiler
+% lndir ~grasp/ghc/compiler # make the link tree -- takes time!
+
+% mkdir tests # lndir doesn't mess w/ "tests" subdirs
+% touch tests/Jmakefile
+\end{verbatim}
+
+This is going to be a setup called \tr{boot} (still for the project
+\tr{ghc}). The ``make world'' system requires that the following
+files exist (they can be empty):
+\begin{verbatim}
+ghc% ll mkworld/*boot*
+-rw-rw-r-- 1 partain grasp 0 Aug 6 20:36 mkworld/AllProjects-ghc-boot.otmpl
+-rw-rw-r-- 1 partain grasp 0 Aug 6 20:35 mkworld/Jmake-ghc-boot.orules
+-rw-rw-r-- 1 partain grasp 0 Aug 6 20:36 mkworld/Project-ghc-boot.otmpl
+-rw-rw-r-- 1 partain grasp 133 Aug 6 20:50 mkworld/site-ghc-boot.odef
+\end{verbatim}
+
+Now, we need to tell the ``make world'' system about this special setup and
+to tell it about the new ``top of the world'' (\tr{~grasp/ghc-boot}), I do:
+\begin{verbatim}
+% cd ghc-boot/compiler
+% rm Makefile
+% ../mkworld/jmake -P ghc -S boot -I../mkworld -DTopDirPwd=/users/fp/grasp/ghc-boot -DTopDir=../. -DCurDir=./compiler
+../mkworld/site-ghc.odef: 9: TopDirPwd redefined
+\end{verbatim}
+(It's brute force, but it works! The crucial bits are: \tr{-S boot},
+and \tr{-DTopDirPwd=/users/fp/grasp/ghc-boot}.)
+
+Test that your \tr{Makefile} stuff is OK by...
+\begin{verbatim}
+% make Makefile
+% make Makefiles
+% make clean # tidy up some of the junk:
+ # won't work until the Makefiles are properly made
+\end{verbatim}
+
+I had to fiddle some of the ``make world'' flags mentioned above even
+after I'd made my Makefiles. No problem---after the fiddles, just do:
+\begin{verbatim}
+% make Makefile
+% make Makefiles
+% make depend
+\end{verbatim}
+(All three should have been successfully at some point before getting
+down to business.)
+
+In my case, getting down to business was something like...
+\begin{verbatim}
+% fastmake -k hcs
+\end{verbatim}
+
+\begin{onlystandalone}
+\printindex
+\end{document}
+\end{onlystandalone}
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/Jmakefile b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/Jmakefile
new file mode 100644
index 0000000000..b04c8d2a70
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/Jmakefile
@@ -0,0 +1,6 @@
+LitStuffNeededHere(docs depend)
+InfoStuffNeededHere(docs)
+
+GENLIT_OPTS = -I$(JMAKESRC)
+
+LitDocRootTarget(mkw_ref,lit)
diff --git a/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/mkw_ref.lit b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/mkw_ref.lit
new file mode 100644
index 0000000000..5136c69543
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/docs/mkworld_ref/mkw_ref.lit
@@ -0,0 +1,72 @@
+\begin{onlystandalone}
+\documentstyle[11pt,literate,a4wide]{article}
+\begin{document}
+\title{``Make world'' configuration files}
+\author{Will Partain}
+\date{September 1992}
+\maketitle
+\begin{rawlatex}
+\tableofcontents
+\end{rawlatex}
+\end{onlystandalone}
+
+\begin{onlypartofdoc}
+\section[mkworld-files]{``Make world'' configuration files}
+\downsection
+\end{onlypartofdoc}
+
+% some intro needs to go here (ToDo)
+
+%----------------------------------------------------------------
+% template that shows the structure
+\input{TEMPLATE.ljm}
+
+%----------------------------------------------------------------
+\section[mkworld-general]{General mkworld files}
+\downsection
+
+\section[mkworld-gen-platform]{General platform-ish mkworld files}
+\downsection
+\input{plat-TRIGGERS.ljm}
+\input{plat-DEF.ljm}
+\upsection
+
+\section[mkworld-gen-site]{General site-ish mkworld files}
+\downsection
+\section[site.jm]{@site.jm@ is included HERE...}
+
+This is a file, prepared by hand, that records (a few) facts about the
+local computing environment, e.g., where @perl@ lives, whether you
+have the GNU C compiler, etc.
+
+\input{site-DEF.ljm}
+\upsection
+
+\input{suffixes-GEN.ljm}
+\input{macros-GEN.ljm}
+\input{utils-GEN.ljm}
+\upsection
+
+%----------------------------------------------------------------
+\section[mkworld-project-files]{Project-specific mkworld files}
+
+The @*.jm@ files specific to a project, or to a setup of a project,
+can be used either to define brand-new stuff, or to override bits of
+the general stuff in this document.
+
+You can get a ``literate source'' document for the @*.ljm@ files that
+come with the @ghc@ and/or @nofib@ projects. Check in those projects'
+individual \tr{mkworld/} directories.
+
+%\downsection
+%\input{ghc/root.lit}
+%\input{nofib/root.lit}
+%\upsection
+
+\begin{onlypartofdoc}
+\upsection
+\end{onlypartofdoc}
+\begin{onlystandalone}
+\printindex
+\end{document}
+\end{onlystandalone}
diff --git a/web/glasgow/lit2x-0.16/mkworld/install-GEN.jm b/web/glasgow/lit2x-0.16/mkworld/install-GEN.jm
new file mode 100644
index 0000000000..64adf3044c
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/install-GEN.jm
@@ -0,0 +1,139 @@
+# line 1 "install-GEN.ljm"
+# line 8 "install-GEN.ljm"
+/*# Where and how to install things (generally) */
+/*# [An individual project is likely to have its own ideas] */
+/*# WHERE: */
+
+#ifndef InstRootDir
+#define InstRootDir /usr/local
+#endif
+/* platform-specific binaries */
+#ifndef InstBinDir
+#define InstBinDir $(INSTROOT)/bin/$(HOSTPLATFORM)
+#endif
+/* scripts are platform-independent executables */
+#ifndef InstScriptDir
+#define InstScriptDir $(INSTROOT)/bin
+#endif
+/* "Lib" is where platform-specific stuff goes;
+ * "Data" is where platform-independent stuff goes.
+ * [arbitrary]
+ */
+#ifndef InstLibDir
+#define InstLibDir $(INSTROOT)/lib/$(HOSTPLATFORM)
+#endif
+#ifndef InstDataDir
+#define InstDataDir $(INSTROOT)/lib
+#endif
+INSTROOT = InstRootDir
+INSTBINDIR = InstBinDir
+INSTSCRIPTDIR = InstScriptDir
+INSTLIBDIR = InstLibDir
+INSTDATADIR = InstDataDir
+
+/* top of manual page tree to install in */
+/* NB: not necessarily the same place as to look for man pages (?) */
+#ifndef InstManRoot
+#define InstManRoot ManDirectoryRoot
+#endif
+/* prefix for man page _sources_ (vs .../cat) */
+#ifndef InstManSrcRoot
+#define InstManSrcRoot $(INSTMANROOT)/man
+#endif
+/* man pages for commands */
+#ifndef InstComManDir /* man pages for commands */
+#define InstComManDir CAT2($(INSTMANSRCROOT),$(COMMANSUFFIX))
+#endif
+/* man pages for library routines */
+#ifndef InstLibManDir
+#define InstLibManDir CAT2($(INSTMANSRCROOT),$(LIBMANSUFFIX))
+#endif
+/* man pages for system commands */
+#ifndef InstSysManDir
+#define InstSysManDir CAT2($(INSTMANSRCROOT),$(SYSMANSUFFIX))
+#endif
+
+/* suffix for installing commands'/etcs' man pages */
+#ifndef ComManSuffix
+#define ComManSuffix l /* use just one tab or cpp will die */
+#endif
+#ifndef LibManSuffix
+#define LibManSuffix 3 /* use just one tab or cpp will die */
+#endif
+#ifndef SysManSuffix
+#define SysManSuffix 8 /* use just one tab or cpp will die */
+#endif
+INSTMANROOT = InstManRoot
+INSTMANSRCROOT = InstManSrcRoot
+INSTCOMMANDIR = InstComManDir
+INSTLIBMANDIR = InstLibManDir
+INSTSYSMANDIR = InstSysManDir
+COMMANSUFFIX = ComManSuffix
+LIBMANSUFFIX = LibManSuffix
+SYSMANSUFFIX = SysManSuffix
+
+#ifndef InstInfoDir
+#define InstInfoDir $(INSTROOT)/info
+#endif
+INSTINFODIR = InstInfoDir
+
+/*# HOW: */
+/* this stuff about "who" does the installing doesn't have make vars
+ * as it is not intended to be runtime-changeable.
+ */
+#ifndef InstOwner
+#ifdef Owner
+#define InstOwner -o Owner
+#else
+#define InstOwner /* as nothing */
+#endif
+#endif
+#ifndef InstGroup
+#ifdef Group
+#define InstGroup -g Group
+#else
+#define InstGroup /* as nothing */
+#endif
+#endif
+
+#ifndef InstFileFlags
+#define InstFileFlags /* as nothing */
+#endif
+#ifndef InstStrip
+#define InstStrip /* as nothing */
+#endif
+#ifndef InstBinFlags
+#define InstBinFlags -m 0755 InstOwner InstGroup InstFileFlags InstStrip
+#endif
+/*
+ No strip flags on rest of these -- avoids message from install
+ about stripping non-binaries.
+*/
+#ifndef InstScriptFlags
+#define InstScriptFlags -m 0755 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstLibFlags
+#define InstLibFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstDataLibFlags
+#define InstDataLibFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstIncFlags
+#define InstIncFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstDataFlags
+#define InstDataFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstManFlags
+#define InstManFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstRanlibFlags
+#define InstRanlibFlags /*none*/
+#endif
+INSTBINFLAGS = InstBinFlags
+INSTSCRIPTFLAGS = InstScriptFlags
+INSTLIBFLAGS = InstLibFlags
+INSTINCFLAGS = InstIncFlags /* flags for include files */
+INSTDATAFLAGS = InstDataFlags
+INSTMANFLAGS = InstManFlags
+INSTRANLIBFLAGS = InstRanlibFlags
diff --git a/web/glasgow/lit2x-0.16/mkworld/install-GEN.ljm b/web/glasgow/lit2x-0.16/mkworld/install-GEN.ljm
new file mode 100644
index 0000000000..615223d66a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/install-GEN.ljm
@@ -0,0 +1,145 @@
+%************************************************************************
+%* *
+\section[mkworld-install-GEN]{General stuff about installing things}
+%* *
+%************************************************************************
+
+\begin{code}
+/*# Where and how to install things (generally) */
+/*# [An individual project is likely to have its own ideas] */
+/*# WHERE: */
+
+#ifndef InstRootDir
+#define InstRootDir /usr/local
+#endif
+/* platform-specific binaries */
+#ifndef InstBinDir
+#define InstBinDir $(INSTROOT)/bin/$(HOSTPLATFORM)
+#endif
+/* scripts are platform-independent executables */
+#ifndef InstScriptDir
+#define InstScriptDir $(INSTROOT)/bin
+#endif
+/* "Lib" is where platform-specific stuff goes;
+ * "Data" is where platform-independent stuff goes.
+ * [arbitrary]
+ */
+#ifndef InstLibDir
+#define InstLibDir $(INSTROOT)/lib/$(HOSTPLATFORM)
+#endif
+#ifndef InstDataDir
+#define InstDataDir $(INSTROOT)/lib
+#endif
+INSTROOT = InstRootDir
+INSTBINDIR = InstBinDir
+INSTSCRIPTDIR = InstScriptDir
+INSTLIBDIR = InstLibDir
+INSTDATADIR = InstDataDir
+
+/* top of manual page tree to install in */
+/* NB: not necessarily the same place as to look for man pages (?) */
+#ifndef InstManRoot
+#define InstManRoot ManDirectoryRoot
+#endif
+/* prefix for man page _sources_ (vs .../cat) */
+#ifndef InstManSrcRoot
+#define InstManSrcRoot $(INSTMANROOT)/man
+#endif
+/* man pages for commands */
+#ifndef InstComManDir /* man pages for commands */
+#define InstComManDir CAT2($(INSTMANSRCROOT),$(COMMANSUFFIX))
+#endif
+/* man pages for library routines */
+#ifndef InstLibManDir
+#define InstLibManDir CAT2($(INSTMANSRCROOT),$(LIBMANSUFFIX))
+#endif
+/* man pages for system commands */
+#ifndef InstSysManDir
+#define InstSysManDir CAT2($(INSTMANSRCROOT),$(SYSMANSUFFIX))
+#endif
+
+/* suffix for installing commands'/etcs' man pages */
+#ifndef ComManSuffix
+#define ComManSuffix l /* use just one tab or cpp will die */
+#endif
+#ifndef LibManSuffix
+#define LibManSuffix 3 /* use just one tab or cpp will die */
+#endif
+#ifndef SysManSuffix
+#define SysManSuffix 8 /* use just one tab or cpp will die */
+#endif
+INSTMANROOT = InstManRoot
+INSTMANSRCROOT = InstManSrcRoot
+INSTCOMMANDIR = InstComManDir
+INSTLIBMANDIR = InstLibManDir
+INSTSYSMANDIR = InstSysManDir
+COMMANSUFFIX = ComManSuffix
+LIBMANSUFFIX = LibManSuffix
+SYSMANSUFFIX = SysManSuffix
+
+#ifndef InstInfoDir
+#define InstInfoDir $(INSTROOT)/info
+#endif
+INSTINFODIR = InstInfoDir
+
+/*# HOW: */
+/* this stuff about "who" does the installing doesn't have make vars
+ * as it is not intended to be runtime-changeable.
+ */
+#ifndef InstOwner
+#ifdef Owner
+#define InstOwner -o Owner
+#else
+#define InstOwner /* as nothing */
+#endif
+#endif
+#ifndef InstGroup
+#ifdef Group
+#define InstGroup -g Group
+#else
+#define InstGroup /* as nothing */
+#endif
+#endif
+
+#ifndef InstFileFlags
+#define InstFileFlags /* as nothing */
+#endif
+#ifndef InstStrip
+#define InstStrip /* as nothing */
+#endif
+#ifndef InstBinFlags
+#define InstBinFlags -m 0755 InstOwner InstGroup InstFileFlags InstStrip
+#endif
+/*
+ No strip flags on rest of these -- avoids message from install
+ about stripping non-binaries.
+*/
+#ifndef InstScriptFlags
+#define InstScriptFlags -m 0755 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstLibFlags
+#define InstLibFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstDataLibFlags
+#define InstDataLibFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstIncFlags
+#define InstIncFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstDataFlags
+#define InstDataFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstManFlags
+#define InstManFlags -m 0644 InstOwner InstGroup InstFileFlags
+#endif
+#ifndef InstRanlibFlags
+#define InstRanlibFlags /*none*/
+#endif
+INSTBINFLAGS = InstBinFlags
+INSTSCRIPTFLAGS = InstScriptFlags
+INSTLIBFLAGS = InstLibFlags
+INSTINCFLAGS = InstIncFlags /* flags for include files */
+INSTDATAFLAGS = InstDataFlags
+INSTMANFLAGS = InstManFlags
+INSTRANLIBFLAGS = InstRanlibFlags
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/jmake.c b/web/glasgow/lit2x-0.16/mkworld/jmake.c
new file mode 100644
index 0000000000..4fcb5557bc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/jmake.c
@@ -0,0 +1,922 @@
+/*****************************************************************************\
+ BASED ON:
+ $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+ * *
+ * Porting Note *
+ * *
+ * Add the value of BOOTSTRAPCFLAGS to the cpp_argv table (in jmakemdep.h) *
+ * so that it will be passed to the template file. *
+ * *
+\*****************************************************************************/
+
+/*
+ *
+ * Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Original Author:
+ * Todd Brunhoff
+ * Tektronix, inc.
+ * While a guest engineer at Project Athena, MIT
+ *
+ * jmake: the include-make program.
+ *
+ * Usage: jmake [-Idir] [-Ddefine] [-T] [-f jmakefile ] [-s] [-e] [-v] [make flags]
+ *
+ * Jmake takes a template makefile (TEMPLATE.jm) and runs cpp on it
+ * producing a temporary makefile in /tmp. It then runs make on
+ * this pre-processed makefile.
+ * Options:
+ * -D define. Same as cpp -D argument.
+ * -I Include directory. Same as cpp -I argument.
+ * -T template. Designate a template other
+ * than TEMPLATE.jm
+ * -s[F] show. Show the produced makefile on the standard
+ * output. Make is not run is this case. If a file
+ * argument is provided, the output is placed there.
+ * -e[F] execute instead of show; optionally name Makefile F
+ * -v verbose. Show the make command line executed.
+ *
+ * Environment variables:
+ *
+ * JMAKEINCLUDE Include directory to use in addition to "."
+ * JMAKECPP Cpp to use instead of /lib/cpp
+ * JMAKEMAKE make program to use other than what is
+ * found by searching the $PATH variable.
+ * Other features:
+ * jmake reads the entire cpp output into memory and then scans it
+ * for occurences of "@@". If it encounters them, it replaces it with
+ * a newline. It also trims any trailing white space on output lines
+ * (because make gets upset at them). This helps when cpp expands
+ * multi-line macros but you want them to appear on multiple lines.
+ *
+ * The macros MAKEFILE and MAKE are provided as macros
+ * to make. MAKEFILE is set to jmake's makefile (not the constructed,
+ * preprocessed one) and MAKE is set to argv[0], i.e. the name of
+ * the jmake program.
+ *
+ * Theory of operation:
+ * 1. Determine the name of the jmakefile from the command line (-f)
+ * or from the content of the current directory (Jmakefile or jmakefile).
+ * Call this <jmakefile>. This gets added to the arguments for
+ * make as MAKEFILE=<jmakefile>.
+ * 2. Determine the name of the template from the command line (-T)
+ * or the default, TEMPLATE.jm. Call this <template>
+ * 3. Start up cpp an provide it with three lines of input:
+ * #define JMAKE_TEMPLATE " <template> "
+ * #define INCLUDE_JMAKEFILE < <jmakefile> >
+ * #include JMAKE_TEMPLATE
+ * Note that the define for INCLUDE_JMAKEFILE is intended for
+ * use in the template file. This implies that the jmake is
+ * useless unless the template file contains at least the line
+ * #include INCLUDE_JMAKEFILE
+ * 4. Gather the output from cpp, and clean it up, expanding @@ to
+ * newlines, stripping trailing white space, cpp control lines,
+ * and extra blank lines. This cleaned output is placed in a
+ * temporary file. Call this <makefile>.
+ * 5. Start up make specifying <makefile> as its input.
+ *
+ * The design of the template makefile should therefore be:
+ * <set global macros like CFLAGS, etc.>
+ * <include machine dependent additions>
+ * #include INCLUDE_JMAKEFILE
+ * <add any global targets like 'clean' and long dependencies>
+ */
+#include <stdio.h>
+#if (defined(SVR4) || defined(_IBMR2) || defined(SYSV386)) && __STDC__
+FILE * fdopen();
+#endif
+#include <ctype.h>
+/*partain: #include "Xosdefs.h"*/
+#ifndef X_NOT_POSIX
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE
+#endif
+#endif
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef X_NOT_POSIX
+#include <sys/file.h>
+#else
+#include <unistd.h>
+#endif
+#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#include <sys/stat.h>
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <sys/wait.h>
+#else
+#define _POSIX_SOURCE
+#include <sys/wait.h>
+#undef _POSIX_SOURCE
+#endif
+#define waitCode(w) WEXITSTATUS(w)
+#define waitSig(w) WTERMSIG(w)
+typedef int waitType;
+#else /* X_NOT_POSIX */
+#ifdef SYSV
+#define waitCode(w) (((w) >> 8) & 0x7f)
+#define waitSig(w) ((w) & 0xff)
+typedef int waitType;
+#else /* SYSV */
+#include <sys/wait.h>
+#define waitCode(w) ((w).w_T.w_Retcode)
+#define waitSig(w) ((w).w_T.w_Termsig)
+typedef union wait waitType;
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) waitSig(w)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(w) waitCode(w)
+#endif
+#endif /* X_NOT_POSIX */
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc(), *realloc();
+void exit();
+#endif
+#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
+char *malloc(), *realloc();
+#endif /* macII */
+#ifdef X_NOT_STDC_ENV
+extern char *getenv();
+#endif
+#include <errno.h>
+extern int errno;
+#include "jmakemdep.h"
+
+
+#define TRUE 1
+#define FALSE 0
+
+#ifdef FIXUP_CPP_WHITESPACE
+int InRule = FALSE;
+#endif
+
+/*
+ * Some versions of cpp reduce all tabs in macro expansion to a single
+ * space. In addition, the escaped newline may be replaced with a
+ * space instead of being deleted. Blech.
+ */
+#ifndef FIXUP_CPP_WHITESPACE
+#define KludgeOutputLine(arg)
+#define KludgeResetRule()
+#endif
+
+typedef unsigned char boolean;
+
+#ifndef DEFAULT_CPP
+#ifdef USE_CC_E
+#define DEFAULT_CPP "/bin/cc"
+#else
+#ifdef CPP_PROGRAM
+#define DEFAULT_CPP CPP_PROGRAM
+#else
+#define DEFAULT_CPP "/lib/cpp"
+#endif
+#endif
+#endif
+
+char *cpp = DEFAULT_CPP;
+
+char *tmpMakefile = "/tmp/Imf.XXXXXX";
+char *tmpJmakefile = "/tmp/IIf.XXXXXX";
+char *make_argv[ ARGUMENTS ] = { "make" };
+
+int make_argindex;
+int cpp_argindex;
+char *make = NULL;
+char *Jmakefile = NULL;
+char *Makefile = "Makefile";
+char *Template = "TEMPLATE.jm";
+/* partain: SetupLabel and ProjectLabel are my additions */
+char *SetupLabel = "std";
+char *ProjectLabel = "none";
+char *ProjectMkworldDir = "";
+/* partain: net patch from dubois; orig:
+char *program;
+*/
+char *program = "jmake";
+char *FindJmakefile();
+char *ReadLine();
+char *CleanCppInput();
+char *Strdup();
+char *Emalloc();
+
+boolean verbose = FALSE;
+boolean show = TRUE;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ FILE *tmpfd;
+ char makeMacro[ BUFSIZ ];
+ char makefileMacro[ BUFSIZ ];
+
+ program = argv[0];
+ init();
+ SetOpts(argc, argv);
+#ifdef USE_CC_E
+ AddCppArg("-");
+#endif
+
+ Jmakefile = FindJmakefile(Jmakefile);
+ if (Makefile)
+ tmpMakefile = Makefile;
+ else {
+ tmpMakefile = Strdup(tmpMakefile);
+ (void) mktemp(tmpMakefile);
+ }
+ AddMakeArg("-f");
+ AddMakeArg( tmpMakefile );
+ sprintf(makeMacro, "MAKE=%s", program);
+ AddMakeArg( makeMacro );
+ sprintf(makefileMacro, "MAKEFILE=%s", Jmakefile);
+ AddMakeArg( makefileMacro );
+
+ if ((tmpfd = fopen(tmpMakefile, "w+")) == NULL)
+ LogFatal("Cannot create temporary file %s.", tmpMakefile);
+
+ cppit(Jmakefile, Template, tmpfd, tmpMakefile);
+
+ if (show) {
+ if (Makefile == NULL)
+ showit(tmpfd);
+ } else
+ makeit();
+ wrapup();
+ exit(0);
+}
+
+showit(fd)
+ FILE *fd;
+{
+ char buf[ BUFSIZ ];
+ int red;
+
+ fseek(fd, 0, 0);
+ while ((red = fread(buf, 1, BUFSIZ, fd)) > 0)
+ fwrite(buf, red, 1, stdout);
+ if (red < 0)
+ LogFatal("Cannot write stdout.", "");
+}
+
+wrapup()
+{
+ if (tmpMakefile != Makefile)
+ unlink(tmpMakefile);
+ unlink(tmpJmakefile);
+}
+
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+catch(sig)
+ int sig;
+{
+ errno = 0;
+ LogFatalI("Signal %d.", sig);
+}
+
+/*
+ * Initialize some variables.
+ */
+init()
+{
+ char *p;
+
+ make_argindex=0;
+ while (make_argv[ make_argindex ] != NULL)
+ make_argindex++;
+ cpp_argindex = 0;
+ while (cpp_argv[ cpp_argindex ] != NULL)
+ cpp_argindex++;
+
+ /*
+ * See if the standard include directory is different than
+ * the default. Or if cpp is not the default. Or if the make
+ * found by the PATH variable is not the default.
+ */
+ if (p = getenv("JMAKEINCLUDE")) {
+ if (*p != '-' || *(p+1) != 'I')
+ LogFatal("Environment var JMAKEINCLUDE %s\n",
+ "must begin with -I");
+ AddCppArg(p);
+ for (; *p; p++)
+ if (*p == ' ') {
+ *p++ = '\0';
+ AddCppArg(p);
+ }
+ }
+ if (p = getenv("JMAKECPP"))
+ cpp = p;
+ if (p = getenv("JMAKEMAKE"))
+ make = p;
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, catch);
+}
+
+AddMakeArg(arg)
+ char *arg;
+{
+ errno = 0;
+ if (make_argindex >= ARGUMENTS-1)
+ LogFatal("Out of internal storage.", "");
+ make_argv[ make_argindex++ ] = arg;
+ make_argv[ make_argindex ] = NULL;
+}
+
+AddCppArg(arg)
+ char *arg;
+{
+ errno = 0;
+ if (cpp_argindex >= ARGUMENTS-1)
+ LogFatal("Out of internal storage.", "");
+ cpp_argv[ cpp_argindex++ ] = arg;
+ cpp_argv[ cpp_argindex ] = NULL;
+}
+
+SetOpts(argc, argv)
+ int argc;
+ char **argv;
+{
+ errno = 0;
+ /*
+ * Now gather the arguments for make
+ */
+ for(argc--, argv++; argc; argc--, argv++) {
+ /*
+ * We intercept these flags.
+ */
+ if (argv[0][0] == '-') {
+ if (argv[0][1] == 'D') {
+ AddCppArg(argv[0]);
+ } else if (argv[0][1] == 'I') {
+ AddCppArg(argv[0]);
+ } else if (argv[0][1] == 'f') {
+ if (argv[0][2])
+ Jmakefile = argv[0]+2;
+ else {
+ argc--, argv++;
+ if (! argc)
+ LogFatal("No description arg after -f flag\n", "");
+ Jmakefile = argv[0];
+ }
+ } else if (argv[0][1] == 's') {
+ if (argv[0][2])
+ Makefile = ((argv[0][2] == '-') && !argv[0][3]) ?
+ NULL : argv[0]+2;
+ else {
+ argc--, argv++;
+ if (!argc)
+ LogFatal("No description arg after -s flag\n", "");
+ Makefile = ((argv[0][0] == '-') && !argv[0][1]) ?
+ NULL : argv[0];
+ }
+ show = TRUE;
+ } else if (argv[0][1] == 'e') {
+ Makefile = (argv[0][2] ? argv[0]+2 : NULL);
+ show = FALSE;
+ } else if (argv[0][1] == 'T') {
+ if (argv[0][2])
+ Template = argv[0]+2;
+ else {
+ argc--, argv++;
+ if (! argc)
+ LogFatal("No description arg after -T flag\n", "");
+ Template = argv[0];
+ }
+/* partain added -P <project>, -S <setup>, and -C <dir> (project mkworld dir) options */
+ } else if (argv[0][1] == 'P') {
+ if (argv[0][2])
+ ProjectLabel = argv[0]+2;
+ else {
+ argc--, argv++;
+ if (! argc)
+ LogFatal("No description arg after -P flag\n", "");
+ ProjectLabel = argv[0];
+ }
+ } else if (argv[0][1] == 'S') {
+ if (argv[0][2])
+ SetupLabel = argv[0]+2;
+ else {
+ argc--, argv++;
+ if (! argc)
+ LogFatal("No description arg after -S flag\n", "");
+ SetupLabel = argv[0];
+ }
+ } else if (argv[0][1] == 'C') {
+ if (argv[0][2])
+ ProjectMkworldDir = argv[0]+2;
+ else {
+ argc--, argv++;
+ if (! argc)
+ LogFatal("No description arg after -C flag\n", "");
+ ProjectMkworldDir = argv[0];
+ }
+ { char *temp = Emalloc(4096); /* hack */
+ strcat(temp, "-I");
+ strcat(temp, ProjectMkworldDir);
+ AddCppArg(temp);
+ }
+/* end of addition */
+ } else if (argv[0][1] == 'v') {
+ verbose = TRUE;
+ } else
+ AddMakeArg(argv[0]);
+ } else
+ AddMakeArg(argv[0]);
+ }
+}
+
+char *FindJmakefile(Jmakefile)
+ char *Jmakefile;
+{
+ int fd;
+
+ if (Jmakefile) {
+ if ((fd = open(Jmakefile, O_RDONLY)) < 0)
+ LogFatal("Cannot open %s.", Jmakefile);
+ } else {
+ if ((fd = open("Jmakefile", O_RDONLY)) < 0)
+ LogFatal("No description file (Jmakefile).", "");
+ else
+ Jmakefile = "Jmakefile";
+ }
+ close (fd);
+ return(Jmakefile);
+}
+
+LogFatalI(s, i)
+ char *s;
+ int i;
+{
+ /*NOSTRICT*/
+ LogFatal(s, (char *)i);
+}
+
+LogFatal(x0,x1)
+ char *x0, *x1;
+{
+ extern char *sys_errlist[];
+ static boolean entered = FALSE;
+
+ if (entered)
+ return;
+ entered = TRUE;
+
+ fprintf(stderr, "%s: ", program);
+ if (errno)
+ fprintf(stderr, "%s: ", sys_errlist[ errno ]);
+ fprintf(stderr, x0,x1);
+ fprintf(stderr, " Stop.\n");
+ wrapup();
+ exit(1);
+}
+
+showargs(argv)
+ char **argv;
+{
+ for (; *argv; argv++)
+ fprintf(stderr, "%s ", *argv);
+ fprintf(stderr, "\n");
+}
+
+cppit(Jmakefile, template, outfd, outfname)
+ char *Jmakefile;
+ char *template;
+ FILE *outfd;
+ char *outfname;
+{
+ FILE *pipeFile;
+ int pid, pipefd[2];
+ waitType status;
+ char *cleanedJmakefile;
+
+ /*
+ * Get a pipe.
+ */
+ if (pipe(pipefd) < 0)
+ LogFatal("Cannot make a pipe.", "");
+
+ /*
+ * Fork and exec cpp
+ */
+ pid = fork();
+ if (pid < 0)
+ LogFatal("Cannot fork.", "");
+ if (pid) { /* parent */
+ close(pipefd[0]);
+ cleanedJmakefile = CleanCppInput(Jmakefile);
+ if ((pipeFile = fdopen(pipefd[1], "w")) == NULL)
+ LogFatalI("Cannot fdopen fd %d for output.", pipefd[1]);
+
+ fprintf(pipeFile, "#define JMAKE_TEMPLATE\t\"%s\"\n",
+ template);
+ fprintf(pipeFile, "#define INCLUDE_JMAKEFILE\t<%s>\n",
+ cleanedJmakefile);
+
+/* partain added OVERRIDE_FILEs business */
+ fprintf(pipeFile, "#define SetupLabel\t%s\n", SetupLabel);
+ fprintf(pipeFile, "#define SetupIsStd\t%d\n", (! strcmp("std", SetupLabel)));
+ fprintf(pipeFile, "#define ProjectLabel\t%s\n", ProjectLabel);
+ fprintf(pipeFile, "#define ProjectIsNone\t%d\n", (! strcmp("none", ProjectLabel)));
+ if (strcmp("", ProjectMkworldDir) != 0) {
+ fprintf(pipeFile, "#define HaveProjectMkworldDir\t1\n");
+ fprintf(pipeFile, "#define ProjectMkworldDir\t%s\n", ProjectMkworldDir);
+ }
+
+ fprintf(pipeFile, "#define SITE_SETUP_FILE\t\"site-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define SITE_PROJECT_FILE\t\"site-%s.jm\"\n",
+ ProjectLabel);
+
+ fprintf(pipeFile, "#define ONLY4_SETUP_FILE\t\"only4-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define ONLY4_PROJECT_FILE\t\"only4-%s.jm\"\n",
+ ProjectLabel);
+
+ fprintf(pipeFile, "#define SUFFIXES_SETUP_FILE\t\"suffixes-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define SUFFIXES_PROJECT_FILE\t\"suffixes-%s.jm\"\n",
+ ProjectLabel);
+
+ fprintf(pipeFile, "#define MACROS_SETUP_FILE\t\"macros-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define MACROS_PROJECT_FILE\t\"macros-%s.jm\"\n",
+ ProjectLabel);
+
+ fprintf(pipeFile, "#define UTILS_SETUP_FILE\t\"utils-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define UTILS_PROJECT_FILE\t\"utils-%s.jm\"\n",
+ ProjectLabel);
+
+ fprintf(pipeFile, "#define INSTALLATION_SETUP_FILE\t\"install-%s-%s.jm\"\n",
+ ProjectLabel, SetupLabel);
+ fprintf(pipeFile, "#define INSTALLATION_PROJECT_FILE\t\"install-%s.jm\"\n",
+ ProjectLabel);
+/* end of addition */
+
+ fprintf(pipeFile, "#include JMAKE_TEMPLATE\n");
+ fclose(pipeFile);
+ while (wait(&status) > 0) {
+ errno = 0;
+ if (WIFSIGNALED(status))
+ LogFatalI("Signal %d.", waitSig(status));
+ if (WIFEXITED(status) && waitCode(status))
+ LogFatalI("Exit code %d.", waitCode(status));
+ }
+#ifdef linux
+ freopen(outfname, "r+", outfd);
+#endif
+ CleanCppOutput(outfd, outfname);
+ } else { /* child... dup and exec cpp */
+ if (verbose)
+ showargs(cpp_argv);
+ dup2(pipefd[0], 0);
+ dup2(fileno(outfd), 1);
+ close(pipefd[1]);
+ execv(cpp, cpp_argv);
+ LogFatal("Cannot exec %s.", cpp);
+ }
+}
+
+makeit()
+{
+ int pid;
+ waitType status;
+
+ /*
+ * Fork and exec make
+ */
+ pid = fork();
+ if (pid < 0)
+ LogFatal("Cannot fork.", "");
+ if (pid) { /* parent... simply wait */
+ while (wait(&status) > 0) {
+ errno = 0;
+ if (WIFSIGNALED(status))
+ LogFatalI("Signal %d.", waitSig(status));
+ if (WIFEXITED(status) && waitCode(status))
+ LogFatalI("Exit code %d.", waitCode(status));
+ }
+ } else { /* child... dup and exec cpp */
+ if (verbose)
+ showargs(make_argv);
+ if (make)
+ execv(make, make_argv);
+ else
+ execvp("make", make_argv);
+ LogFatal("Cannot exec %s.", make);
+ }
+}
+
+char *CleanCppInput(Jmakefile)
+ char *Jmakefile;
+{
+ FILE *outFile = NULL;
+ int infd;
+ char *buf, /* buffer for file content */
+ *pbuf, /* walking pointer to buf */
+ *punwritten, /* pointer to unwritten portion of buf */
+ *cleanedJmakefile = Jmakefile, /* return value */
+ *ptoken, /* pointer to # token */
+ *pend, /* pointer to end of # token */
+ savec; /* temporary character holder */
+ struct stat st;
+
+ /*
+ * grab the entire file.
+ */
+ if ((infd = open(Jmakefile, O_RDONLY)) < 0)
+ LogFatal("Cannot open %s for input.", Jmakefile);
+ fstat(infd, &st);
+ buf = Emalloc(st.st_size+1);
+ if (read(infd, buf, st.st_size) != st.st_size)
+ LogFatal("Cannot read all of %s:", Jmakefile);
+ close(infd);
+ buf[ st.st_size ] = '\0';
+
+ punwritten = pbuf = buf;
+ while (*pbuf) {
+ /* pad make comments for cpp */
+ if (*pbuf == '#' && (pbuf == buf || pbuf[-1] == '\n')) {
+
+ ptoken = pbuf+1;
+ while (*ptoken == ' ' || *ptoken == '\t')
+ ptoken++;
+ pend = ptoken;
+ while (*pend && *pend != ' ' && *pend != '\t' && *pend != '\n')
+ pend++;
+ savec = *pend;
+ *pend = '\0';
+ if (strcmp(ptoken, "include")
+ && strcmp(ptoken, "define")
+ && strcmp(ptoken, "undef")
+ && strcmp(ptoken, "ifdef")
+ && strcmp(ptoken, "ifndef")
+ && strcmp(ptoken, "else")
+ && strcmp(ptoken, "endif")
+ && strcmp(ptoken, "if")) {
+ if (outFile == NULL) {
+ tmpJmakefile = Strdup(tmpJmakefile);
+ (void) mktemp(tmpJmakefile);
+ cleanedJmakefile = tmpJmakefile;
+ outFile = fopen(tmpJmakefile, "w");
+ if (outFile == NULL)
+ LogFatal("Cannot open %s for write.\n",
+ tmpJmakefile);
+ }
+ fwrite(punwritten, sizeof(char), pbuf-punwritten, outFile);
+ fputs("/**/", outFile);
+ punwritten = pbuf;
+ }
+ *pend = savec;
+ }
+ pbuf++;
+ }
+ if (outFile) {
+ fwrite(punwritten, sizeof(char), pbuf-punwritten, outFile);
+ fclose(outFile); /* also closes the pipe */
+ }
+
+ return(cleanedJmakefile);
+}
+
+CleanCppOutput(tmpfd, tmpfname)
+ FILE *tmpfd;
+ char *tmpfname;
+{
+ char *input;
+ int blankline = 0;
+
+ while(input = ReadLine(tmpfd, tmpfname)) {
+ if (isempty(input)) {
+ if (blankline++)
+ continue;
+ KludgeResetRule();
+ } else {
+ blankline = 0;
+ KludgeOutputLine(&input);
+ fputs(input, tmpfd);
+ }
+ putc('\n', tmpfd);
+ }
+ fflush(tmpfd);
+#ifdef NFS_STDOUT_BUG
+ /*
+ * On some systems, NFS seems to leave a large number of nulls at
+ * the end of the file. Ralph Swick says that this kludge makes the
+ * problem go away.
+ */
+ ftruncate (fileno(tmpfd), (off_t)ftell(tmpfd));
+#endif
+}
+
+/*
+ * Determine of a line has nothing in it. As a side effect, we trim white
+ * space from the end of the line. Cpp magic cookies are also thrown away.
+ */
+isempty(line)
+ char *line;
+{
+ char *pend;
+
+ /*
+ * Check for lines of the form
+ * # n "...
+ * or
+ * # line n "...
+ */
+ if (*line == '#') {
+ pend = line+1;
+ if (*pend == ' ')
+ pend++;
+ if (strncmp(pend, "line ", 5) == 0)
+ pend += 5;
+ if (isdigit(*pend)) {
+ while (isdigit(*pend))
+ pend++;
+ if (*pend++ == ' ' && *pend == '"')
+ return(TRUE);
+ }
+ }
+
+ /*
+ * Find the end of the line and then walk back.
+ */
+ for (pend=line; *pend; pend++) ;
+
+ pend--;
+ while (pend >= line && (*pend == ' ' || *pend == '\t'))
+ pend--;
+ *++pend = '\0';
+ return (*line == '\0');
+}
+
+/*ARGSUSED*/
+char *ReadLine(tmpfd, tmpfname)
+ FILE *tmpfd;
+ char *tmpfname;
+{
+ static boolean initialized = FALSE;
+ static char *buf, *pline, *end;
+ char *p1, *p2;
+
+ if (! initialized) {
+ int total_red;
+ struct stat st;
+
+ /*
+ * Slurp it all up.
+ */
+ fseek(tmpfd, 0, 0);
+ fstat(fileno(tmpfd), &st);
+ pline = buf = Emalloc(st.st_size+1);
+#ifdef linux
+ total_red = fread(buf, 1, st.st_size, tmpfd);
+#else
+ total_red = read(fileno(tmpfd), buf, st.st_size);
+#endif
+ if (total_red != st.st_size)
+ LogFatal("cannot read %s\n", tmpMakefile);
+ end = buf + st.st_size;
+ *end = '\0';
+#ifdef linux
+ fseek(tmpfd, 0, 0);
+#else
+ lseek(fileno(tmpfd), 0, 0);
+#endif
+#ifdef SYSV
+ freopen(tmpfname, "w+", tmpfd);
+#else /* !SYSV */
+ ftruncate(fileno(tmpfd), 0);
+#endif /* !SYSV */
+ initialized = TRUE;
+ fprintf (tmpfd, "# Makefile generated by jmake -- DO NOT EDIT!!!\n");
+ fprintf (tmpfd, "# (edit the Jmakefile instead)\n");
+/* partain: no thanks
+ fprintf (tmpfd, "# %s\n",
+ "$XConsortium: jmake.c,v 1.51 89/12/12 12:37:30 jim Exp $");
+*/
+#ifdef FIXUP_CPP_WHITESPACE
+ {
+ static char *cpp_warning[] = {
+"#",
+"# The cpp used on this machine replaces all newlines and multiple tabs and",
+"# spaces in a macro expansion with a single space. Jmake tries to compensate",
+"# for this, but is not always successful.",
+"#",
+NULL };
+ char **cpp;
+
+ for (cpp = cpp_warning; *cpp; cpp++) {
+ fprintf (tmpfd, "%s\n", *cpp);
+ }
+ }
+#endif /* FIXUP_CPP_WHITESPACE */
+ }
+
+ for (p1 = pline; p1 < end; p1++) {
+ if (*p1 == '@' && *(p1+1) == '@') { /* soft EOL */
+ *p1++ = '\0';
+ p1++; /* skip over second @ */
+ break;
+ }
+ else if (*p1 == '\n') { /* real EOL */
+ *p1++ = '\0';
+ break;
+ }
+ }
+
+ /*
+ * return NULL at the end of the file.
+ */
+ p2 = (pline == p1 ? NULL : pline);
+ pline = p1;
+ return(p2);
+}
+
+writetmpfile(fd, buf, cnt)
+ FILE *fd;
+ int cnt;
+ char *buf;
+{
+ errno = 0;
+ if (fwrite(buf, cnt, 1, fd) != 1)
+ LogFatal("Cannot write to %s.", tmpMakefile);
+}
+
+char *Emalloc(size)
+ int size;
+{
+ char *p;
+
+ if ((p = malloc(size)) == NULL)
+ LogFatalI("Cannot allocate %d bytes\n", size);
+ return(p);
+}
+
+#ifdef FIXUP_CPP_WHITESPACE
+KludgeOutputLine(pline)
+ char **pline;
+{
+ char *p = *pline;
+
+ switch (*p) {
+ case '#': /*Comment - ignore*/
+ break;
+ case '\t': /*Already tabbed - ignore it*/
+ break;
+ case ' ': /*May need a tab*/
+ default:
+ for (; *p; p++) if (p[0] == ':' &&
+ p > *pline && p[-1] != '\\') {
+ if (**pline == ' ')
+ (*pline)++;
+ InRule = TRUE;
+ break;
+ }
+ if (InRule && **pline == ' ')
+ **pline = '\t';
+ break;
+ }
+}
+
+KludgeResetRule()
+{
+ InRule = FALSE;
+}
+#endif /* FIXUP_CPP_WHITESPACE */
+
+char *Strdup(cp)
+ register char *cp;
+{
+ register char *new = Emalloc(strlen(cp) + 1);
+
+ strcpy(new, cp);
+ return new;
+}
diff --git a/web/glasgow/lit2x-0.16/mkworld/jmakemdep.h b/web/glasgow/lit2x-0.16/mkworld/jmakemdep.h
new file mode 100644
index 0000000000..579ef097cc
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/jmakemdep.h
@@ -0,0 +1,379 @@
+/*
+ * Based on:
+ * $XConsortium: imakemdep.h,v 1.38 91/08/25 11:36:39 rws Exp $
+ *
+ * This file contains machine-dependent constants for the jmake utility. When
+ * porting jmake, read each of the steps below and add in any necessary
+ * definitions. Do *not* edit ccjmake.c or jmake.c!
+ */
+
+#ifdef CCJMAKE
+/*
+ * Step 1: jmake_ccflags
+ * Define any special flags that will be needed to get jmake.c to compile.
+ * These will be passed to the compile along with the contents of the
+ * make variable BOOTSTRAPCFLAGS.
+ */
+#ifdef hpux
+#ifdef hp9000s800
+#define jmake_ccflags "-DSYSV"
+#else
+#define jmake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV"
+#endif
+#endif
+
+#if defined(macII) || defined(_AUX_SOURCE)
+#define jmake_ccflags "-DmacII -DSYSV"
+#endif
+
+#ifdef stellar
+#define jmake_ccflags "-DSYSV"
+#endif
+
+#ifdef att
+#define jmake_ccflags "-Xc -DSVR4"
+#endif
+
+#ifdef sony
+#ifdef SYSTYPE_SYSV
+#define jmake_ccflags "-DSVR4"
+#else
+#include <sys/param.h>
+#if NEWSOS < 41
+#define jmake_ccflags "-Dbsd43 -DNOSTDHDRS"
+#else
+#define jmake_ccflags "-Dbsd43"
+#endif
+#endif
+#endif
+
+#ifdef CRAY
+/* -DX_NOT_STDC_ENV is just so we can bootstrap with cc instead of scc */
+#define jmake_ccflags "-DSYSV -DUSG -DX_NOT_STDC_ENV"
+#endif
+
+#ifdef _IBMR2
+#define jmake_ccflags "-Daix -DSYSV -D_IBMR2"
+#else
+#ifdef aix
+#define jmake_ccflags "-Daix -DSYSV"
+#endif
+#endif
+
+#ifdef Mips
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+# define jmake_ccflags "-DMips -DBSD43"
+# else
+# define jmake_ccflags "-DMips -DSYSV"
+# endif
+#endif
+
+/* OLD:
+#ifdef mips
+#ifdef SYSTYPE_SYSV
+#define jmake_ccflags "-DSYSV -I/usr/include/bsd -lbsd"
+#endif
+#endif
+*/
+
+#ifdef is68k
+#define jmake_ccflags "-Dluna -Duniosb"
+#endif
+
+#ifdef SYSV386
+# ifdef SVR4
+# define jmake_ccflags "-Xc -DSVR4"
+# else
+# define jmake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef __convex__
+#define jmake_ccflags "-fn -tm c1"
+#endif
+
+#ifdef apollo
+#define jmake_ccflags "-DX_NOT_POSIX"
+#endif
+
+#else /* not CCJMAKE */
+#ifndef MAKEDEPEND
+/*
+ * Step 2: dup2
+ * If your OS doesn't have a dup2() system call to duplicate one file
+ * descriptor onto another, define such a mechanism here (if you don't
+ * already fall under the existing category(ies).
+ */
+#if defined(SYSV) && !defined(CRAY) && !defined(Mips)
+#define dup2(fd1,fd2) ((fd1 == fd2) ? fd1 : (close(fd2), \
+ fcntl(fd1, F_DUPFD, fd2)))
+#endif
+
+
+/*
+ * Step 3: FIXUP_CPP_WHITESPACE
+ * If your cpp collapses tabs macro expansions into a single space and
+ * replaces escaped newlines with a space, define this symbol. This will
+ * cause jmake to attempt to patch up the generated Makefile by looking
+ * for lines that have colons in them (this is why the rules file escapes
+ * all colons). One way to tell if you need this is to see whether or not
+ * your Makefiles have no tabs in them and lots of @@ strings.
+ */
+#if defined(sun) \
+ || defined(linux) \
+ || defined(__alpha)
+#define FIXUP_CPP_WHITESPACE
+#endif
+
+
+/*
+ * Step 4: DEFAULT_CPP
+ * If the C preprocessor does not live in /lib/cpp, set this symbol to
+ * the appropriate location.
+ */
+#ifdef apollo
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#if defined(_IBMR2) && !defined(DEFAULT_CPP)
+#define DEFAULT_CPP "/usr/lpp/X11/Xamples/util/cpp/cpp"
+#endif
+
+/*
+ * Step 5: cpp_argv
+ * The following table contains the cpp flags that should be passed to
+ * cpp whenever a Makefile is being generated. If your preprocessor
+ * doesn't predefine any unique symbols, choose one and add it to the
+ * end of this table. Then, do the following:
+ *
+ * a. Use this symbol at the top of Jmake.tmpl when setting MacroFile.
+ * b. Put this symbol in the definition of BootstrapCFlags in your
+ * <platform>.cf file.
+ * c. When doing a make World, always add "BOOTSTRAPCFLAGS=-Dsymbol"
+ * to the end of the command line.
+ *
+ * Note that you may define more than one symbols (useful for platforms
+ * that support multiple operating systems).
+ */
+
+#define ARGUMENTS 50 /* number of arguments in various arrays */
+char *cpp_argv[ARGUMENTS] = {
+#ifdef USE_CC_E
+ "cc", /* replaced by the actual cpp program to exec */
+ "-E",
+#else
+ "cpp", /* replaced by the actual cpp program to exec */
+#endif /* USE_CC_E */
+ "-I.", /* add current directory to include path */
+#ifdef unix
+ "-Uunix", /* remove unix symbol so that filename unix.c okay */
+#endif
+#ifdef M4330
+ "-DM4330", /* Tektronix */
+#endif
+#ifdef M4310
+ "-DM4310", /* Tektronix */
+#endif
+#if defined(macII) || defined(_AUX_SOURCE)
+ "-DmacII", /* Apple A/UX */
+#endif
+#ifdef att
+ "-Datt", /* AT&T products */
+#endif
+#ifdef sony
+ "-Dsony", /* Sony */
+#ifndef SYSTYPE_SYSV
+ "-Dbsd43",
+#endif
+#endif
+#ifdef _IBMR2
+ "-D_IBMR2", /* IBM RS-6000 (we ensured that aix is defined above) */
+#ifndef aix
+#define aix /* allow BOOTSTRAPCFLAGS="-D_IBMR2" */
+#endif
+#endif /* _IBMR2 */
+#ifdef aix
+ "-Daix", /* AIX instead of AOS */
+#ifndef ibm
+#define ibm /* allow BOOTSTRAPCFLAGS="-Daix" */
+#endif
+#endif /* aix */
+#ifdef ibm
+ "-Dibm", /* IBM PS/2 and RT under both AOS and AIX */
+#endif
+#ifdef luna
+ "-Dluna", /* OMRON luna 68K and 88K */
+#ifdef luna1
+ "-Dluna1",
+#endif
+#ifdef luna88k /* need not on UniOS-Mach Vers. 1.13 */
+ "-traditional", /* for some older version */
+#endif /* instead of "-DXCOMM=\\#" */
+#ifdef uniosb
+ "-Duniosb",
+#endif
+#ifdef uniosu
+ "-Duniosu",
+#endif
+#endif /* luna */
+#ifdef CRAY /* Cray */
+ "-Ucray",
+#endif
+#ifdef Mips
+ "-DMips", /* Define and use Mips for Mips Co. OS/mach. */
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+ "-DBSD43", /* Mips RISCOS supports two environments */
+# else
+ "-DSYSV", /* System V environment is the default */
+# endif
+#endif /* Mips */
+#ifdef MOTOROLA
+ "-DMOTOROLA", /* Motorola Delta Systems */
+# ifdef SYSV
+ "-DSYSV",
+# endif
+# ifdef SVR4
+ "-DSVR4",
+# endif
+#endif /* MOTOROLA */
+#ifdef SYSV386 /* System V/386 folks */
+ "-DSYSV386",
+# ifdef SVR4
+ "-DSVR4",
+# endif
+# ifdef ISC
+ "-DISC", /* ISC 2.2.1 */
+# endif
+# ifdef SCO
+ "-DSCO",
+# endif
+# ifdef ESIX
+ "-DESIX",
+# endif
+# ifdef ATT
+ "-DATT",
+# endif
+# ifdef DELL
+ "-DDELL",
+# endif
+#endif
+#ifdef linux
+ "-traditional",
+#endif
+#ifdef __alpha
+ "-traditional",
+#endif
+};
+#else /* else MAKEDEPEND */
+/*
+ * Step 6: predefs
+ * If your compiler and/or preprocessor define any specific symbols, add
+ * them to the the following table. The definition of struct symtab is
+ * in util/makedepend/def.h.
+ */
+struct symtab predefs[] = {
+#ifdef apollo
+ {"apollo", "1"},
+#endif
+#ifdef ibm032
+ {"ibm032", "1"},
+#endif
+#ifdef ibm
+ {"ibm", "1"},
+#endif
+#ifdef aix
+ {"aix", "1"},
+#endif
+#ifdef sun
+ {"sun", "1"},
+#endif
+#ifdef hpux
+ {"hpux", "1"},
+#endif
+#ifdef vax
+ {"vax", "1"},
+#endif
+#ifdef VMS
+ {"VMS", "1"},
+#endif
+#ifdef cray
+ {"cray", "1"},
+#endif
+#ifdef CRAY
+ {"CRAY", "1"},
+#endif
+#ifdef att
+ {"att", "1"},
+#endif
+#ifdef mips
+ {"mips", "1"},
+#endif
+#ifdef ultrix
+ {"ultrix", "1"},
+#endif
+#ifdef stellar
+ {"stellar", "1"},
+#endif
+#ifdef mc68000
+ {"mc68000", "1"},
+#endif
+#ifdef mc68020
+ {"mc68020", "1"},
+#endif
+#ifdef __GNUC__
+ {"__GNUC__", "1"},
+#endif
+#if __STDC__
+ {"__STDC__", "1"},
+#endif
+#ifdef __HIGHC__
+ {"__HIGHC__", "1"},
+#endif
+#ifdef CMU
+ {"CMU", "1"},
+#endif
+#ifdef luna
+ {"luna", "1"},
+#ifdef luna1
+ {"luna1", "1"},
+#endif
+#ifdef luna2
+ {"luna2", "1"},
+#endif
+#ifdef luna88k
+ {"luna88k", "1"},
+#endif
+#ifdef uniosb
+ {"uniosb", "1"},
+#endif
+#ifdef uniosu
+ {"uniosu", "1"},
+#endif
+#endif
+#ifdef ieeep754
+ {"ieeep754", "1"},
+#endif
+#ifdef is68k
+ {"is68k", "1"},
+#endif
+#ifdef m68k
+ {"m68k", "1"},
+#endif
+#ifdef m88k
+ {"m88k", "1"},
+#endif
+#ifdef bsd43
+ {"bsd43", "1"},
+#endif
+#ifdef hcx
+ {"hcx", 1},
+#endif
+#if defined(alpha) || defined(__alpha) || defined(__alpha__)
+ {"__alpha__", 1},
+#endif
+ /* add any additional symbols before this line */
+ {NULL, NULL}
+};
+
+#endif /* MAKEDEPEND */
+#endif /* CCJMAKE */
+
diff --git a/web/glasgow/lit2x-0.16/mkworld/jmkmf.prl b/web/glasgow/lit2x-0.16/mkworld/jmkmf.prl
new file mode 100644
index 0000000000..fe4dcd2edf
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/jmkmf.prl
@@ -0,0 +1,130 @@
+# this *.prl file is shoved through "msub"
+#
+# generate a Makefile from a Jmakefile from _outside_ [only] the GHC
+# sources!
+#
+# based on X11R4 xmkmf /bin/sh script via Paul DuBois
+#
+# uses:
+# (1) a new project with no special jmake requirements; want to use
+# installed "none"-project stuff:
+# type% cd top-of-project-sources
+# type% jmkmf
+#
+# (2) a new project with a "project-label" (and maybe a "setup-label")
+#
+# type% cd top-of-project-sources
+# type% jmkmf -P project-label -S setup-label [-C project-config-dir]
+#
+# (3) for a project using installed utils, jmkmf will be invoked when
+# "make Makefile" happens:
+#
+# jmkmf -P <proj-label> -S <setup-label> - -DTopDir=<foo> -DTopDirPwd=<bar> -DCurDir=<baz>
+#
+# The "-" separates the getopt-able options from the rest.
+#
+# The -S option may be omitted if "setup-label" is "std" and -C option
+# may be omitted if the project's config files happen to live in the
+# std place (see -A).
+#
+# The "-A allprojects-config-dir" option may be used to override
+# jmkmf's built-in idea of where the jmake config files are installed.
+#
+# don't let people fiddle with TopDir and CurDir
+#
+$Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/;
+$Status = 0;
+do 'getopts.pl' || die "Giant error 'do'ing getopts.pl: $@";
+$Usage = "usage: $Pgm ".
+ '[-v] '.
+ '[-P project-label] '.
+ '[-S setup-label] '.
+ '[-C project-config-dir] '.
+ '[-A alternate-installed-config-dir] '.
+ "[- args to pass on to jmake]\n";
+
+$TopDir = '.';
+$CurDir = '.';
+$jmake_extra_args = '';
+
+chop($TopDirPwd = `pwd`);
+$TopDirPwd =~ s/^\/tmp_mnt//; # anti-NFS attack
+
+if ( ! &Getopts('A:C:P:S:v')) {
+ print STDERR $Usage;
+ exit 1;
+} else {
+ while ($#ARGV >= 0) {
+ $_ = $ARGV[0]; shift(@ARGV);
+ next if /^-$/;
+ $TopDir = $1, next if /^-DTopDir=(.*)$/;
+ $TopDirPwd = $1, next if /^-DTopDirPwd=(.*)$/;
+ $CurDir = $1, next if /^-DCurDir=(.*)$/;
+ $jmake_extra_args .= " $_";
+ }
+}
+
+$Verbose = ($opt_v) ? 1 : 0;
+$Project_label = ($opt_P) ? $opt_P : 'none';
+$Setup_label = ($opt_S) ? $opt_S : 'std';
+$Project_config_dir = ($opt_C) ? $opt_C : '';
+# the next line fixed up by msub
+$Std_config_dir = ($opt_A) ? $opt_A
+ : (( $(INSTALLING) ) ? '$(INSTDATADIR_MKWORLD)'
+ : '$(TOP_PWD)/$(CURRENT_DIR)');
+
+# chk that all the config and dirs files will be there if needed?
+
+# relative-ise Project_config_dir
+$Have_project_config_dir = '';
+$Project_config_dir_is_relative = '';
+if ($Project_config_dir) {
+ $Have_project_config_dir = '-DHaveProjectConfigDir';
+ $Real_project_config_dir = $Project_config_dir;
+ if ($Project_config_dir !~ /^\//) {
+ $Project_config_dir_is_relative = '-DRelativeProjectConfigDir';
+ if (! $TopDir) {
+ print STDERR "$Pgm: I don't know what TopDir is\n";
+ } else {
+ $Real_project_config_dir= "$TopDir/$Project_config_dir";
+ }
+ }
+ # tidy the name
+ $Project_config_dir =~ s/^(\.\/)+/\.\//;
+}
+
+# do it
+if ( -f Makefile ) {
+ print STDERR "mv Makefile Makefile.bak\n";
+ $Makefile_moved = 1;
+ (system('mv -f Makefile Makefile.bak') >> 8) && die "$Pgm: mv -f Makefile Makefile.bak: failed\n";
+} else {
+ $Makefile_moved = 0;
+}
+
+# should this always -DUseInstalledUtils?
+
+$jmake_args = "-DUseInstalledUtils -P $Project_label -S $Setup_label";
+
+$jmake_args .= " $Have_project_config_dir";
+$jmake_args .= " $Project_config_dir_is_relative";
+if ($Project_config_dir) {
+ $jmake_args .= " -DProjectConfigDir=$Project_config_dir -I$Real_project_config_dir";
+}
+$jmake_args .= " -I$Std_config_dir";
+$jmake_args .= " -DTopDir=$TopDir -DTopDirPwd=$TopDirPwd -DCurDir=$CurDir";
+$jmake_args .= $jmake_extra_args;
+
+print STDERR "jmake $jmake_args\n";
+if (system("jmake $jmake_args") >> 8) {
+ if ($Makefile_moved) {
+ print STDERR "$Pgm: trying to restore Makefile...\n";
+ rename('Makefile.bak','Makefile') || die "$Pgm: mv Makefile.bak Makefile: failed\n";
+ } else {
+ unlink('Makefile'); # don't want to confuse the issue
+ }
+ exit(1);
+}
+# chmod 0444, 'Makefile';
+exit 0;
+
diff --git a/web/glasgow/lit2x-0.16/mkworld/jrestoredeps b/web/glasgow/lit2x-0.16/mkworld/jrestoredeps
new file mode 100644
index 0000000000..510185f727
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/jrestoredeps
@@ -0,0 +1,63 @@
+eval "exec perl -S $0 $*"
+ if $running_under_some_random_shell;
+#
+$Verbose = 0;
+if ($ARGV[0] eq '-v') {
+ $Verbose++;
+ shift(@ARGV);
+}
+# assuming we've just saved a Makefile as Makefile.bak
+# and run "jmake" to make a new Makefile, we now want
+# to grab all the old "make depend" stuff from Makefile.bak and
+# re-glue it onto the new Makefile.
+
+open(MKF, "< Makefile") || die "Can't open Makefile\n";
+open(NEW, "> Makefile.new") || die "Can't open Makefile.new\n";
+while (<MKF>) {
+ # don't go past a "# DO NOT DELETE" line
+ last if /^# DO NOT DELETE/;
+
+ # major HACK (to sidestep whitespace kludgery in jmake)
+ # IF a Makefile line starts with a tab
+ # AND IF it uses a make-variable followed by a backslashed semi-colon,
+ # THEN un-backslash the semi-colon. MEGA-SIGH
+ if (/^\t/ && /\$\([A-Z][A-Z_]*\\:/) {
+ s/(\$\([A-Z][A-Z_]*)\\:/\1:/g;
+ }
+
+ # while here, we may as well tidy up some mess that
+ # an ANSI cpp can cause:
+ s/\$\(\s*([_A-Z]+)\s\)/\$\(\1\)/g;
+
+ # while we're here, we might as well tidy up any directory names...
+ # s|/[^/.][^/]*/\.\.||g; # nuke: /<dir>/..
+ # s|/\.[^.][^/]*/\.\.||g; # nuke: /./.. (and others)
+ # s| \./| |;
+
+ print NEW $_;
+}
+close(MKF);
+
+open(BAK, "< Makefile.bak") || exit(0); # die "Can't open Makefile.bak\n";
+
+# skip to "# DO NOT DELETE"
+$_ = <BAK>;
+while ($_ && ! /^# DO NOT DELETE/ ) {
+ $_ = <BAK>;
+}
+if (! $_) {
+ print STDERR "No old dependencies to restore were found in Makefile.bak\n"
+ if $Verbose;
+} else {
+ # copy through "DO NOT DELETE" line
+ print NEW $_;
+
+ # copy through the rest
+ while (<BAK>) { print NEW $_; }
+
+ close(NEW);
+ close(BAK);
+}
+
+# now rename Makefile.new to Makefile.
+rename('Makefile.new', 'Makefile');
diff --git a/web/glasgow/lit2x-0.16/mkworld/macros-GEN.jm b/web/glasgow/lit2x-0.16/mkworld/macros-GEN.jm
new file mode 100644
index 0000000000..42c950824d
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/macros-GEN.jm
@@ -0,0 +1,853 @@
+# line 19 "../../mkworld/macros-GEN.ljm"
+#ifndef CDependTarget
+#define CDependTarget(deps) @@\
+MkDependCNeededHere(depend) @@\
+ @@\
+depend:: deps @@\
+ $(MKDEPENDC) $(MKDEPENDCFLAGS) -- $(CFLAGS) -- deps
+#endif /* CDependTarget */
+# line 31 "../../mkworld/macros-GEN.ljm"
+#ifndef HaskellDependTarget
+#define HaskellDependTarget(deps) @@\
+MkDependHSNeededHere(depend) @@\
+ @@\
+depend:: deps @@\
+ $(MKDEPENDHS) $(MKDEPENDHSFLAGS) -- $(HCFLAGS) -- deps
+#endif /* HaskellDependTarget */
+# line 43 "../../mkworld/macros-GEN.ljm"
+#ifndef LitDependTarget
+#define LitDependTarget(root,rootext) @@\
+ @@\
+depend:: @@\
+ $(MKDEPENDLIT) $(MKDEPENDLITFLAGS) root.rootext
+#endif /* LitDependTarget */
+# line 61 "../../mkworld/macros-GEN.ljm"
+#ifndef AllTarget
+#define AllTarget(depends) @@\
+all:: depends
+#endif
+# line 71 "../../mkworld/macros-GEN.ljm"
+#ifndef LinkTarget
+#define LinkTarget(target,linkto) @@\
+AllTarget(target) @@\
+ExtraStuffToClean(target) @@\
+target:: linkto @@\
+ RemoveTarget(target) @@\
+ ${LN} linkto target
+#endif
+# line 101 "../../mkworld/macros-GEN.ljm"
+#ifndef BuildPgm
+#define BuildPgm(program,compiler,compileropts,objs,libs,deplibs) @@\
+AllTarget(program) @@\
+ExtraStuffToClean(program) @@\
+program:: objs deplibs @@\
+ RemoveTarget($@) @@\
+ compiler -o $@ compileropts $(LDOPTIONS) objs libs
+#endif /* BuildPgm */
+# line 121 "../../mkworld/macros-GEN.ljm"
+#ifndef BuildPgmFromCFiles
+#define BuildPgmFromCFiles(program,objs,libs,deplibs) @@\
+BuildPgm(program,$(CC),$(CFLAGS),objs,libs,deplibs)
+#endif
+
+#ifndef BuildPgmFromOneCFile
+#define BuildPgmFromOneCFile(program) @@\
+SRCS_C = program.c @@\
+OBJS_C = program.o @@\
+BuildPgm(program,$(CC),$(CFLAGS),$(OBJS_C),/**/,/**/)
+#endif
+# line 137 "../../mkworld/macros-GEN.ljm"
+/*ToDo: cmp => $(CMP)*/
+
+#ifndef YaccRunWithExpectMsg
+#define YaccRunWithExpectMsg(srcfile,ss,rs) @@\
+srcfile.tab.c : srcfile.y @@\
+ $(RM) srcfile.tab.c srcfile.tab.h-SAVE y.tab.c y.tab.h y.output @@\
+ @if [ -f srcfile.tab.h ] ; then $(MV) -f srcfile.tab.h srcfile.tab.h-SAVE ; fi @@\
+ @echo expect ss shift/reduce conflicts and rs reduce/reduce conflicts @@\
+ $(YACC) $(YFLAGS) srcfile.y @@\
+ @if cmp -s srcfile.tab.h-SAVE y.tab.h ; then \ @@\
+ $(MV) -f srcfile.tab.h-SAVE srcfile.tab.h ; \ @@\
+ else \ @@\
+ echo $(MV) -f y.tab.h srcfile.tab.h ; \ @@\
+ $(MV) -f y.tab.h srcfile.tab.h ; \ @@\
+ chmod 444 srcfile.tab.h ; \ @@\
+ fi @@\
+ @$(RM) y.tab.h @@\
+ $(MV) y.tab.c srcfile.tab.c @@\
+ @chmod 444 srcfile.tab.c @@\
+ @@\
+srcfile.tab.h : srcfile.tab.c @@\
+ @echo -n "" /* no-op */
+#endif
+# line 182 "../../mkworld/macros-GEN.ljm"
+#ifndef BuildPgmFromHaskellModules
+#define BuildPgmFromHaskellModules(program,objs,libs,deplibs) @@\
+BuildPgm(program,$(HC),$(HCFLAGS),objs,libs,deplibs)
+#endif
+
+#ifndef BuildPgmFromOneHaskellModule
+#define BuildPgmFromOneHaskellModule(program,module,isuf) @@\
+SRCS_HS = module.isuf @@\
+OBJS_HS = module.o @@\
+BuildPgm(program,$(HC),$(HCFLAGS),$(OBJS_HS),,)
+#endif
+# line 197 "../../mkworld/macros-GEN.ljm"
+#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ $(RM) $@ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ $(HC) flags module_isuf -o module.o \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+
+#elif HaveChalmersHBC == YES && UseChalmersHBC == YES
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ @echo $(RM) $@; \ @@\
+ $(RM) $@; \ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ if [ -f $(@D)/$$iface ] ; then \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \ @@\
+ fi ; \ @@\
+ set +e; \ @@\
+ echo $(HC) flags module_isuf -o module.o; \ @@\
+ $(HC) flags module_isuf -o module.o; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ if cmp -s $(@D)/$$iface-SAVE $(@D)/$$iface ; then \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ else \ @@\
+ if [ -f $(@D)/$$iface-SAVE ] ; then \ @@\
+ diff -c1 $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ fi ; \ @@\
+ fi \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+#else /* not GHC or HBC; presumably prototype Glasgow compiler (nhc) */
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ @echo $(RM) $@; \ @@\
+ $(RM) $@; \ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ if [ -f $(@D)/$$iface ] ; then \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \ @@\
+ cp -p $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ chmod u+w $(@D)/$$iface ; \ @@\
+ fi ; \ @@\
+ set +e; \ @@\
+ echo $(HC) flags module_isuf -o module.o; \ @@\
+ $(HC) flags module_isuf -o module.o; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ $(RM) STAT ; \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ if [ -f STAT ] ; then $(MV) STAT module.STAT ; fi ; \ @@\
+ if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \ @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ $(UPDATEIFACE) $$iface $(@D)/$$iface ; \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ fi \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+#endif /* ! ChalmersHBC or GHC */
+# line 270 "../../mkworld/macros-GEN.ljm"
+#ifndef HaskellCompilePreProcessing
+#define HaskellCompilePreProcessing(module_isuf,module,isuf) /* nothing */
+#endif /* ! HaskellCompilePreProcessing */
+
+#ifndef HaskellCompilePostProcessing
+#define HaskellCompilePostProcessing(module_isuf,module,isuf) /* nothing */
+#endif /* ! HaskellCompilePostProcessing */
+# line 281 "../../mkworld/macros-GEN.ljm"
+#ifndef HaskellCompileWithSpecifiedFlags
+#define HaskellCompileWithSpecifiedFlags(module,isuf,flags) @@\
+module.o : module.isuf \
+_body_HaskellCompileWithSpecifiedFlags(module.isuf,module,isuf,flags)
+#endif /* HaskellCompileWithSpecifiedFlags */
+
+#ifndef HaskellCompileWithExtraFlags
+#define HaskellCompileWithExtraFlags(module,isuf,flags) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) flags)
+#endif /* HaskellCompileWithExtraFlags */
+
+#ifndef HaskellCompile
+#define HaskellCompile(module,isuf) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS))
+#endif /* HaskellCompile */
+# line 301 "../../mkworld/macros-GEN.ljm"
+#ifndef HaskellCompileWithMoreHeapAndStack
+#define HaskellCompileWithMoreHeapAndStack(module,isuf,heapsize,stksize) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize) HaskellCompilerStkSize(stksize))
+#endif /* HaskellCompileWithMoreHeapAndStack */
+
+#ifndef HaskellCompileWithMoreHeap
+#define HaskellCompileWithMoreHeap(module,isuf,heapsize) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize))
+#endif /* HaskellCompileWithMoreHeap */
+# line 314 "../../mkworld/macros-GEN.ljm"
+#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
+#define HaskellCompilerHeapSize(size) -Rmax-heapsize size
+#define HaskellCompilerStkSize(size) -Rmax-stksize size
+#define HaskellCompilerRunCpp() -cpp
+#define HaskellEndRTSFlags() /*none*/
+
+#elif HaveChalmersHBC == YES && UseChalmersHBC == YES
+#define HaskellCompilerHeapSize(size) CAT2(-H,size)
+#define HaskellCompilerStkSize(size) CAT2(-V,size)
+#define HaskellCompilerRunCpp() -M
+#define HaskellEndRTSFlags() -
+
+#else /* not GHC or HBC; assume nhc */
+#define HaskellCompilerHeapSize(size) CAT2(-H,size)
+#define HaskellCompilerStkSize(size) /*cant set stksize*/
+#define HaskellCompilerRunCpp() /*none*/
+#define HaskellEndRTSFlags() -
+
+#endif /* not GHC or HBC */
+# line 342 "../../mkworld/macros-GEN.ljm"
+#ifndef ProgramScriptTarget
+#if HasExecableScripts /* can use #! */
+#define ProgramScriptTarget(prog,dst,src,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ cat src >> $@ @@\
+ chmod a+x $@
+#else
+#define ProgramScriptTarget(prog,dst,src,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ cat src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@
+#endif /* HasExecableScripts */
+#endif /* ProgramScriptTarget */
+# line 372 "../../mkworld/macros-GEN.ljm"
+#ifndef MsubTarget
+#define MsubTarget(dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(MSUB) flags src > dst
+#endif
+# line 388 "../../mkworld/macros-GEN.ljm"
+#ifndef MsubProgramScriptTarget
+#if HasExecableScripts /* can use #! */
+#define MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ ${MSUB} flags src >> $@ @@\
+ chmod a+x $@
+#else
+#define MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ ${MSUB} flags src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@
+#endif /* HasExecableScripts */
+#endif /* MsubProgramScriptTarget */
+# line 420 "../../mkworld/macros-GEN.ljm"
+#ifndef MsubMakefileDependentProgramScriptTarget
+#define MsubMakefileDependentProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+ @@\
+Makefile:: @@\
+ $(RM) dst
+#endif
+# line 430 "../../mkworld/macros-GEN.ljm"
+#ifndef MsubScriptTarget
+#define MsubScriptTarget(dst,src,flags,deplist) @@\
+MsubProgramScriptTarget(${SHELL},dst,src,flags,deplist)
+#endif
+# line 445 "../../mkworld/macros-GEN.ljm"
+#ifndef NormalLibraryTarget
+#define NormalLibraryTarget(libname,objlist) @@\
+AllTarget(CAT2(lib,libname.a)) @@\
+ExtraStuffToClean(CAT2(lib,libname.a)) @@\
+CAT2(lib,libname.a):: objlist @@\
+ $(RM) $@ @@\
+ $(AR) $@ objlist @@\
+ $(RANLIB) $@
+#endif /* NormalLibraryTarget */
+# line 465 "../../mkworld/macros-GEN.ljm"
+#ifndef RuntestsTarget
+#define RuntestsTarget(depends) @@\
+runtests:: CAT2(runtest_,depends)
+#endif
+
+#ifndef RunStdTestTimeCmd
+#define RunStdTestTimeCmd /*none*/
+#endif
+
+#ifndef RunStdTest
+#define RunStdTest(name,prog,teststuff) @@\
+RuntestsTarget(name) @@\
+CAT2(runtest_,name):: @@\
+ @RunStdTestTimeCmd $(RUNSTDTEST) prog $(RUNSTDTEST_FLAGS) teststuff
+#endif /* RunStdTest */
+
+#ifndef AsPartOfTest
+#define AsPartOfTest(test,cmdline) @@\
+RuntestsTarget(test) @@\
+CAT2(runtest_,test):: @@\
+ cmdline
+#endif /* AsPartOfTest */
+# line 499 "../../mkworld/macros-GEN.ljm"
+#ifndef InstallMsubbedScriptTarget
+#if HasExecableScripts /* can use #! */
+#define InstallMsubbedScriptTarget(prog,dst,src,installdir) @@\
+dst-tmp: src @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ ${MSUB} INSTALLING=1 src >> $@ @@\
+ chmod a+x $@ @@\
+ @@\
+InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,) @@\
+install:: @@\
+ $(RM) dst-tmp
+#else
+#define InstallMsubbedScriptTarget(prog,dst,src,installdir) @@\
+dst-tmp: src @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ ${MSUB} INSTALLING=1 src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@ @@\
+ @@\
+InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,) @@\
+install:: @@\
+ $(RM) dst-tmp
+#endif /* HasExecableScripts */
+#endif /* InstallMsubbedScriptTarget */
+
+/*
+ INSTALLATION RULES. InstallTarget() should be a part of nearly
+ all of these, to add the target to the "install" rule.
+*/
+
+#ifndef InstallTarget
+#define InstallTarget(depends) @@\
+install:: CAT2(install_,depends)
+#endif
+
+#ifndef InstallDocTarget
+#define InstallDocTarget(depends) @@\
+install_docs:: CAT2(install_doc_,depends)
+#endif
+
+/*
+ Install a target specifying the flags to use. Many of the following
+ installation rules are instantiated as a particular expansion of this.
+*/
+
+#ifndef InstallTargetWithNameAndFlags
+#define InstallTargetWithNameAndFlags(target,destdir,new_name,flags) @@\
+InstallTarget(new_name) @@\
+CAT2(install_,new_name):: target @@\
+ $(INSTALL) -c flags target destdir/new_name
+#endif
+
+#ifndef InstallTargetWithFlags
+#define InstallTargetWithFlags(target,dest,flags) @@\
+InstallTargetWithNameAndFlags(target,dest,target,flags)
+#endif
+
+#ifndef InstallDocTargetWithFlags
+#define InstallDocTargetWithFlags(src,presuff,target,postsuff,dest,flags) @@\
+InstallDocTarget(CAT3(target,_,postsuff)) @@\
+CAT4(install_doc_,target,_,postsuff):: src.presuff @@\
+ $(INSTALL) -c flags src.presuff dest/target.postsuff
+#endif
+
+/*
+ Install a program
+*/
+
+#ifndef InstallBinaryTarget
+#define InstallBinaryTarget(program,dest) @@\
+InstallTargetWithFlags(program,dest,$(INSTBINFLAGS))
+#endif
+
+/* Install a setuid/setgid/etc program -- DELETED (partain)
+*/
+
+/*
+ Install an executable script
+*/
+
+#ifndef InstallScriptTarget
+#define InstallScriptTarget(script,dest) @@\
+InstallTargetWithFlags(script,dest,$(INSTSCRIPTFLAGS))
+#endif
+
+/*
+ Install a library (platform-dependent)
+*/
+
+#ifndef InstallLibraryTarget
+#define InstallLibraryTarget(libname,dest) @@\
+InstallTargetWithFlags(CAT2(lib,libname).a,dest,$(INSTLIBFLAGS)) @@\
+ ${RANLIB} dest/CAT2(lib,libname).a
+#endif
+
+/*
+ Install an include file
+*/
+
+#ifndef InstallIncludeTarget
+#define InstallIncludeTarget(file,dest) @@\
+InstallTargetWithFlags(file,dest,$(INSTINCFLAGS))
+#endif
+
+/*
+ Install a non-executable or data file (these are equivalent)
+*/
+
+#ifndef InstallDataTarget
+#define InstallDataTarget(file,dest) @@\
+InstallTargetWithFlags(file,dest,$(INSTDATAFLAGS))
+#endif
+
+/*
+ Install a set of non-executable files
+
+ DUMP THIS SOMETIME.
+*/
+
+#ifndef InstallMultNonExecTargets
+#define InstallMultNonExecTargets(rule,targets,dest) @@\
+CAT2(install_,rule):: rule @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in targets ;\ @@\
+ do \ @@\
+ echo $(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \ @@\
+ $(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \ @@\
+ done
+#endif
+
+/*
+ Install a man page.
+
+ THIS IS WRONG - rules in Jmakefiles don't have suffix!
+
+ file srcsuffix destdir dstsuffix ???
+*/
+
+#ifndef InstallManPageTarget
+#define InstallManPageTarget(file,destdir,suffix) @@\
+InstallDocTargetWithFlags(file,man,file,suffix,destdir,$(INSTMANFLAGS))
+#endif
+
+#ifndef InstallInfoFileTarget
+#define InstallInfoFileTarget(src,target,destdir) @@\
+InstallDocTargetWithFlags(src,info,target,info,destdir,$(INSTMANFLAGS))
+#endif
+
+#ifndef InstallLinkTarget
+#define InstallLinkTarget(target, linkto, dir) @@\
+InstallTarget(target) @@\
+CAT2(install_,target):: CAT2(install_,linkto) @@\
+ RemoveTarget(dir/target) @@\
+ ${LN} dir/linkto dir/target
+#endif
+
+/*
+ Fake install rules for things not installed anywhere
+*/
+
+#ifndef FakeInstallTarget
+#define FakeInstallTarget(target) @@\
+InstallTarget(target) @@\
+CAT2(install_,target):: target @@\
+ @echo target is not installed anywhere.
+#endif
+
+#ifndef FakeInstallLibrary
+#define FakeInstallLibrary(libname) @@\
+InstallTarget(CAT2(lib,libname).a) @@\
+CAT2(install_lib,libname).a:: CAT2(lib,libname).a @@\
+ @echo CAT2(lib,libname).a is not installed anywhere.
+#endif
+# line 689 "../../mkworld/macros-GEN.ljm"
+#ifndef DocsTarget
+#define DocsTarget(depends) @@\
+docs:: depends
+#endif
+
+/* putting the InfoStuffNeededHere in semi-presumes that
+ LitDocRootTarget is only used once per directory (?)
+*/
+#ifndef LitDocRootTargetWithNamedOutput
+#define LitDocRootTargetWithNamedOutput(rootroot,rootext,rootout) @@\
+DocsTarget(rootroot.info rootroot.dvi) @@\
+ExtraStuffToClean(rootroot.info rootroot.dvi rootroot.texi rootroot.tex) @@\
+LitDependTarget(rootroot,rootext) @@\
+ @@\
+rootroot.info:: rootroot.texi @@\
+ RemoveTarget($@) @@\
+ $(MAKEINFO) $(MAKEINFOFLAGS) rootroot.texi \ @@\
+ && $(POSTMAKEINFO) rootroot.info @@\
+ @@\
+rootroot.dvi:: rootroot.tex @@\
+ RemoveTarget($@) @@\
+ $(LTX) rootroot.tex @@\
+ @@\
+rootroot.texi: rootout.itxi @@\
+ RemoveTarget($@) @@\
+ $(LIT2TEXI) -S $(LIT2TEXIFLAGS) -N rootroot.info -o rootroot.texi rootout.itxi @@\
+ @@\
+rootout.itxi: rootroot.rootext @@\
+ RemoveTarget($@) @@\
+ $(LIT2TEXI) -S -c $(LIT2TEXIFLAGS) -o rootout.itxi rootroot.rootext @@\
+ @@\
+rootroot.tex: rootout.itex @@\
+ RemoveTarget($@) @@\
+ $(LIT2LATEX) -S $(LIT2LATEXFLAGS) -o rootroot.tex rootout.itex @@\
+ @@\
+rootout.itex: rootroot.rootext @@\
+ RemoveTarget($@) @@\
+ $(LIT2LATEX) -S -c $(LIT2LATEXFLAGS) -o rootout.itex rootroot.rootext
+#endif /* LitDocRootTargetWithNamedOutput */
+
+#ifndef LitDocRootTarget
+#define LitDocRootTarget(rootroot,rootext) \
+LitDocRootTargetWithNamedOutput(rootroot,rootext,rootroot)
+#endif /* LitDocRootTarget */
+
+#ifndef VerbatimAndTibTarget
+#define VerbatimAndTibTarget(root) @@\
+VerbatimNeededHere(docs root.tex) @@\
+DocsTarget(root.dvi) @@\
+ExtraStuffToClean(root.dvi root.tex)
+#endif /* VerbatimAndTibTarget */
+# line 755 "../../mkworld/macros-GEN.ljm"
+#ifndef ExtraStuffToClean
+#define ExtraStuffToClean(extra) @@\
+clean:: @@\
+ $(RM) extra
+#endif /* ExtraStuffToClean */
+
+#ifndef ExtraStuffToBeVeryClean
+#define ExtraStuffToBeVeryClean(extra) @@\
+veryclean:: @@\
+ $(RM) extra
+#endif /* ExtraStuffToBeVeryClean */
+
+#ifndef RemoveTarget
+#if RemoveTargetByMoving
+#define RemoveTarget(program) \
+$(RM) program; if [ -f program ]; then $(MV) program CAT2(program,~); fi
+#else
+#define RemoveTarget(program) $(RM) program
+#endif /* ! RemoveTargetByMoving */
+#endif /* RemoveTarget */
+/*
+ * CleanTarget - generate rules to remove any garbage files; the #* is here
+ * instead of in the definition of CLEAN_CMD because System V would treat a
+ * pound sign in the CLEAN_CMD variable as a comment.
+ */
+#ifndef CleanTarget
+#define CleanTarget() @@\
+clean:: @@\
+ $(CLEAN_CMD) \#*
+#endif /* CleanTarget */
+
+/*
+ * VeryCleanTarget - generate rules for "make veryclean"; the idea is
+ * that "make clean" does what "you almost always want" and "make
+ * veryclean" removes ALL generated files.
+ */
+#ifndef VeryCleanTarget
+#define VeryCleanTarget() @@\
+veryclean:: @@\
+ $(CLEAN_CMD) \#*
+#endif /* VeryCleanTarget */
+# line 805 "../../mkworld/macros-GEN.ljm"
+/* this should normally precede <>TagsTarget commands */
+/* those commands *append* to the TAGS file */
+#ifndef ClearTagsFile
+#define ClearTagsFile() @@\
+tags:: @@\
+ $(RM) TAGS; touch TAGS
+#endif
+
+/*
+ * CTagsTarget - generate rules to compute tags files for C source code.
+ * (specified as an arg)
+ * partain: we really expect "etags" to be used...
+ */
+#ifndef CTagsTarget
+#define CTagsTarget(srcs) @@\
+tags:: @@\
+ $(CTAGS) -a $(CTAGSFLAGS) srcs
+#endif /* CTagsTarget */
+
+/* Similarly for Perl and Haskell */
+#ifndef PerlTagsTarget
+#define PerlTagsTarget(srcs) @@\
+tags:: @@\
+ $(PERLTAGS) $(PERLTAGSFLAGS) srcs
+#endif /* PerlTagsTarget */
+
+#ifndef HsTagsTarget
+#define HsTagsTarget(srcs) @@\
+tags:: @@\
+ $(HSTAGS) $(HSTAGSFLAGS) srcs
+#endif /* HsTagsTarget */
+# line 850 "../../mkworld/macros-GEN.ljm"
+#ifndef BuildMakefileTarget
+#define BuildMakefileTarget() @@\
+JmakeNeededHere(Makefile) @@\
+ @@\
+Makefile:: $(MYJCONFIGFILES) @@\
+ @@\
+Makefile:: @@\
+ -@if [ -f Makefile ]; then \ @@\
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ @@\
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) @@\
+ $(JRESTOREDEPS) @@\
+ @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi @@\
+ @chmod 444 Makefile @@\
+ @echo ==== The new Makefile is for\: ==== @@\
+ @$(MAKE) whoami || \ @@\
+ ( echo 'Putting old Makefile back (see Makefile.bad)...' && \ @@\
+ $(MV) Makefile Makefile.bad && \ @@\
+ $(MV) Makefile.bak Makefile ) @@\
+ @@\
+whoami:: @@\
+ @echo $(PROJECTNAME), version $(PROJECTVERSION) @@\
+ @echo project\: $(PROJECTLABEL)\; setup\: $(SETUPLABEL) @@\
+ @echo now building on a \`$(BUILDPLATFORM)\' host @@\
+ @echo hoping to run on a \`$(HOSTPLATFORM)\' host
+#endif /* BuildMakefileTarget */
+# line 881 "../../mkworld/macros-GEN.ljm"
+#ifndef MakefileTarget
+#define MakefileTarget() @@\
+BuildMakefileTarget()
+#endif /* MakefileTarget */
+# line 894 "../../mkworld/macros-GEN.ljm"
+#ifndef GenerateOptionsMakeVars
+#define GenerateOptionsMakeVars(PGM,THINGS,AllProjectsPgmThings,PlatformPgmThings,ProjectPgmThings,SetupPgmThings) @@\
+CAT4(GLUED_,PGM,_,THINGS) = AllProjectsPgmThings PlatformPgmThings ProjectPgmThings SetupPgmThings $(CAT3(PGM,_,THINGS)) $(CAT4(EXTRA_,PGM,_,THINGS))
+#endif
+# line 912 "../../mkworld/macros-GEN.ljm"
+#ifndef NamedTargetSubdirs
+#define NamedTargetSubdirs(name,dirs,verb,flags,subname) @@\
+name:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ;\ @@\
+ do \ @@\
+ (cd $$i ; echo verb "in $(CURRENT_DIR)/$$i..."; \ @@\
+ $(MAKE) $(MFLAGS) flags subname); \ @@\
+ done
+#endif
+# line 935 "../../mkworld/macros-GEN.ljm"
+#ifndef NamedMakeSubdirs
+#define NamedMakeSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"making" name,PassCDebugFlags,all)
+#endif /* NamedMakeSubdirs */
+# line 947 "../../mkworld/macros-GEN.ljm"
+#ifndef DependSubdirs
+#define DependSubdirs(dirs) \
+NamedTargetSubdirs(depend,dirs,"making dependencies",/**/,depend)
+#endif /* DependSubdirs */
+# line 962 "../../mkworld/macros-GEN.ljm"
+#ifndef ProjectMakeVarsForAllinSubdirs
+#define ProjectMakeVarsForAllinSubdirs /*none*/
+#endif
+
+#ifndef SetupMakeVarsForAllinSubdirs
+#define SetupMakeVarsForAllinSubdirs /*none*/
+#endif
+
+#ifndef DoAllinSubdirs
+#define DoAllinSubdirs(dirs) \
+NamedTargetSubdirs(all,dirs,"making all",ProjectMakeVarsForAllinSubdirs SetupMakeVarsForAllinSubdirs,all)
+#endif /* DoAllinSubdirs */
+# line 979 "../../mkworld/macros-GEN.ljm"
+#ifndef DoDocsinSubdirs
+#define DoDocsinSubdirs(dirs) \
+NamedTargetSubdirs(docs,dirs,"making docs",/*no make flags*/,docs)
+#endif /* DoDocsinSubdirs */
+# line 990 "../../mkworld/macros-GEN.ljm"
+#ifndef ProjectMakeVarsForRunTestsinSubdirs
+#define ProjectMakeVarsForRunTestsinSubdirs /*none*/
+#endif
+
+#ifndef SetupMakeVarsForRunTestsinSubdirs
+#define SetupMakeVarsForRunTestsinSubdirs /*none*/
+#endif
+
+#ifndef RunTestsSubdirs
+#define RunTestsSubdirs(dirs) \
+NamedTargetSubdirs(runtests,dirs,"running tests",ProjectMakeVarsForRunTestsinSubdirs SetupMakeVarsForRunTestsinSubdirs,runtests)
+#endif /* RunTestsSubdirs */
+# line 1007 "../../mkworld/macros-GEN.ljm"
+#ifndef InstallSubdirs
+#define InstallSubdirs(dirs) \
+NamedTargetSubdirs(install,dirs,"installing",INSTROOT='$(INSTROOT)',install)
+#endif /* InstallSubdirs */
+# line 1016 "../../mkworld/macros-GEN.ljm"
+#ifndef InstallDocsSubdirs
+#define InstallDocsSubdirs(dirs) \
+NamedTargetSubdirs(install_docs,dirs,"installing documentation",INSTROOT='$(INSTROOT)',install_docs)
+#endif /* InstallDocsSubdirs */
+# line 1025 "../../mkworld/macros-GEN.ljm"
+#ifndef NamedCleanSubdirs
+#define NamedCleanSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"cleaning",RM='$(RM)',clean)
+#endif /* NamedCleanSubdirs */
+
+#ifndef CleanSubdirs
+#define CleanSubdirs(dirs) \
+NamedCleanSubdirs(clean,dirs)
+#endif
+# line 1039 "../../mkworld/macros-GEN.ljm"
+#ifndef NamedVeryCleanSubdirs
+#define NamedVeryCleanSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"being veryclean",RM='$(RM)',veryclean)
+#endif /* NamedCleanSubdirs */
+
+#ifndef VeryCleanSubdirs
+#define VeryCleanSubdirs(dirs) \
+NamedVeryCleanSubdirs(veryclean,dirs)
+#endif
+# line 1053 "../../mkworld/macros-GEN.ljm"
+#ifndef NamedTagSubdirs
+#define NamedTagSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"making tags",,tags)
+#endif /* TagSubdirs */
+
+#ifndef TagSubdirs
+#define TagSubdirs(dirs) \
+NamedTagSubdirs(tags,dirs)
+#endif
+# line 1072 "../../mkworld/macros-GEN.ljm"
+#ifndef MakeMakeSubdirs
+#define MakeMakeSubdirs(dirs,target) @@\
+target:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ;\ @@\
+ do \ @@\
+ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ @@\
+ case "$$i" in \ @@\
+ ./?*/?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \ @@\
+ ./?*/?*/?*) newtop=../../../ sub=subsubsub;; \ @@\
+ ./?*/?*) newtop=../../ sub=subsub;; \ @@\
+ ./?*) newtop=../ sub=sub;; \ @@\
+ */?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \ @@\
+ */?*/?*) newtop=../../../ sub=subsubsub;; \ @@\
+ */?*) newtop=../../ sub=subsub;; \ @@\
+ *) newtop=../ sub=sub;; \ @@\
+ esac; \ @@\
+ case "$(TOP)" in \ @@\
+ /?*) newtop= upprefix= ;; \ @@\
+ *) upprefix=../ ;; \ @@\
+ esac; \ @@\
+ $(MAKE) $${sub}dirMakefiles UPPREFIX=$$upprefix NEWTOP=$$newtop \ @@\
+ MAKEFILE_SUBDIR=$$i NEW_CURRENT_DIR=$(CURRENT_DIR)/$$i;\ @@\
+ done
+#endif /* MakeMakeSubdirs */
+# line 1104 "../../mkworld/macros-GEN.ljm"
+#ifndef MakeNsubdirMakefiles
+#define MakeNsubdirMakefiles() @@\
+subdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubsubsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles
+#endif /* MakeNsubdirMakefiles */
+# line 1153 "../../mkworld/macros-GEN.ljm"
+#ifndef MakefileSubdirs
+#define MakefileSubdirs(dirs) @@\
+MakeMakeSubdirs(dirs,Makefiles) @@\
+ @@\
+MakeNsubdirMakefiles()
+#endif /* MakefileSubdirs */
+# line 1162 "../../mkworld/macros-GEN.ljm"
+#ifndef MakeDirectories
+#define MakeDirectories(step,dirs) @@\
+step:: @@\
+ $(MKDIRHIER) dirs
+#endif
+# line 1170 "../../mkworld/macros-GEN.ljm"
+#ifndef LinkDirectories
+#define LinkDirectories(step,dirs,todir) @@\
+step:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ; \ @@\
+ do \ @@\
+ echo "linking $$i to" todir; \ @@\
+ $(LNDIR) todir $$i; \ @@\
+ done
+#endif
diff --git a/web/glasgow/lit2x-0.16/mkworld/macros-GEN.ljm b/web/glasgow/lit2x-0.16/mkworld/macros-GEN.ljm
new file mode 100644
index 0000000000..ec87a7d444
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/macros-GEN.ljm
@@ -0,0 +1,1180 @@
+%************************************************************************
+%* *
+\section[mkworld-macros-GEN]{Mkworld CPP macros for the masses}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-depend]{Macros related to \tr{depend} std target}
+%* *
+%************************************************************************
+
+These \tr{*DependTarget} rules assume the relevant programs are in
+their proper places. They won't reach out and build them for you.
+
+@CDependTarget@: generate rules to compute dependencies for all C files
+in @deps@.
+\begin{code}
+#ifndef CDependTarget
+#define CDependTarget(deps) @@\
+MkDependCNeededHere(depend) @@\
+ @@\
+depend:: deps @@\
+ $(MKDEPENDC) $(MKDEPENDCFLAGS) -- $(CFLAGS) -- deps
+#endif /* CDependTarget */
+\end{code}
+
+@HaskellDependTarget@: generate rules to compute dependencies for all
+Haskell files in @deps@.
+\begin{code}
+#ifndef HaskellDependTarget
+#define HaskellDependTarget(deps) @@\
+MkDependHSNeededHere(depend) @@\
+ @@\
+depend:: deps @@\
+ $(MKDEPENDHS) $(MKDEPENDHSFLAGS) -- $(HCFLAGS) -- deps
+#endif /* HaskellDependTarget */
+\end{code}
+
+@LitDependTarget@: generate rules to compute dependencies for the
+specified ``literate root file''.
+\begin{code}
+#ifndef LitDependTarget
+#define LitDependTarget(root,rootext) @@\
+ @@\
+depend:: @@\
+ $(MKDEPENDLIT) $(MKDEPENDLITFLAGS) root.rootext
+#endif /* LitDependTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-all]{Macros related to \tr{all} std target}
+%* *
+%************************************************************************
+
+First, so easy ones. @AllTarget()@ should be a part of most of these
+to automatically add the target to the \tr{all} rule.
+
+\begin{code}
+#ifndef AllTarget
+#define AllTarget(depends) @@\
+all:: depends
+#endif
+\end{code}
+
+Make a link to a target. Used when several targets use
+the same object under different names.
+
+\begin{code}
+#ifndef LinkTarget
+#define LinkTarget(target,linkto) @@\
+AllTarget(target) @@\
+ExtraStuffToClean(target) @@\
+target:: linkto @@\
+ RemoveTarget(target) @@\
+ ${LN} linkto target
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-macros-bld-pgms]{Compiling modules/files and linking programs}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsubsubsection{General macros}
+%* *
+%************************************************************************
+
+@BuildPgm@: generate rules to compile and link the
+indicated program; since it does not use any default object files, it
+may be used for multiple programs in the same @Jmakefile@.
+
+This target is the general interface for building a single program
+(perhaps one of many in the @Makefile@).
+
+\begin{code}
+#ifndef BuildPgm
+#define BuildPgm(program,compiler,compileropts,objs,libs,deplibs) @@\
+AllTarget(program) @@\
+ExtraStuffToClean(program) @@\
+program:: objs deplibs @@\
+ RemoveTarget($@) @@\
+ compiler -o $@ compileropts $(LDOPTIONS) objs libs
+#endif /* BuildPgm */
+\end{code}
+ToDo: not sure all ``compilers'' will like that -o above...
+
+%************************************************************************
+%* *
+\subsubsubsection{Compile C files, build C programs}
+%* *
+%************************************************************************
+
+These depend on suitable suffix rules existing.
+
+\begin{code}
+#ifndef BuildPgmFromCFiles
+#define BuildPgmFromCFiles(program,objs,libs,deplibs) @@\
+BuildPgm(program,$(CC),$(CFLAGS),objs,libs,deplibs)
+#endif
+
+#ifndef BuildPgmFromOneCFile
+#define BuildPgmFromOneCFile(program) @@\
+SRCS_C = program.c @@\
+OBJS_C = program.o @@\
+BuildPgm(program,$(CC),$(CFLAGS),$(OBJS_C),/**/,/**/)
+#endif
+\end{code}
+
+This rule is formulated, esp \tr{*.tab.h} part, in case you have more
+than one @YaccRunWithExpectMsg@ in a given directory.
+\begin{code}
+/*ToDo: cmp => $(CMP)*/
+
+#ifndef YaccRunWithExpectMsg
+#define YaccRunWithExpectMsg(srcfile,ss,rs) @@\
+srcfile.tab.c : srcfile.y @@\
+ $(RM) srcfile.tab.c srcfile.tab.h-SAVE y.tab.c y.tab.h y.output @@\
+ @if [ -f srcfile.tab.h ] ; then $(MV) -f srcfile.tab.h srcfile.tab.h-SAVE ; fi @@\
+ @echo expect ss shift/reduce conflicts and rs reduce/reduce conflicts @@\
+ $(YACC) $(YFLAGS) srcfile.y @@\
+ @if cmp -s srcfile.tab.h-SAVE y.tab.h ; then \ @@\
+ $(MV) -f srcfile.tab.h-SAVE srcfile.tab.h ; \ @@\
+ else \ @@\
+ echo $(MV) -f y.tab.h srcfile.tab.h ; \ @@\
+ $(MV) -f y.tab.h srcfile.tab.h ; \ @@\
+ chmod 444 srcfile.tab.h ; \ @@\
+ fi @@\
+ @$(RM) y.tab.h @@\
+ $(MV) y.tab.c srcfile.tab.c @@\
+ @chmod 444 srcfile.tab.c @@\
+ @@\
+srcfile.tab.h : srcfile.tab.c @@\
+ @echo -n "" /* no-op */
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsubsection{Compile Haskell modules, build Haskell programs}
+%* *
+%************************************************************************
+
+Defined here...
+\begin{description}
+\item[@BuildPgmFromHaskellModules@:]
+
+\item[@BuildPgmFromOneHaskellModule@:]
+
+\item[@HaskellCompileWithSpecifiedFlags@:]
+\item[@HaskellCompileWithExtraFlags@:]
+\item[@HaskellCompileWithMoreHeapAndStack@:]
+\item[@HaskellCompileWithMoreHeap@:]
+\item[@HaskellCompile@:]
+\end{description}
+
+\begin{code}
+#ifndef BuildPgmFromHaskellModules
+#define BuildPgmFromHaskellModules(program,objs,libs,deplibs) @@\
+BuildPgm(program,$(HC),$(HCFLAGS),objs,libs,deplibs)
+#endif
+
+#ifndef BuildPgmFromOneHaskellModule
+#define BuildPgmFromOneHaskellModule(program,module,isuf) @@\
+SRCS_HS = module.isuf @@\
+OBJS_HS = module.o @@\
+BuildPgm(program,$(HC),$(HCFLAGS),$(OBJS_HS),,)
+#endif
+\end{code}
+
+First, we define just the body of a hs-to-o rule...
+\begin{code}
+#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ $(RM) $@ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ $(HC) flags module_isuf -o module.o \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+
+#elif HaveChalmersHBC == YES && UseChalmersHBC == YES
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ @echo $(RM) $@; \ @@\
+ $(RM) $@; \ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ if [ -f $(@D)/$$iface ] ; then \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \ @@\
+ fi ; \ @@\
+ set +e; \ @@\
+ echo $(HC) flags module_isuf -o module.o; \ @@\
+ $(HC) flags module_isuf -o module.o; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ if cmp -s $(@D)/$$iface-SAVE $(@D)/$$iface ; then \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ else \ @@\
+ if [ -f $(@D)/$$iface-SAVE ] ; then \ @@\
+ diff -c1 $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ fi ; \ @@\
+ fi \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+#else /* not GHC or HBC; presumably prototype Glasgow compiler (nhc) */
+
+#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
+ @echo $(RM) $@; \ @@\
+ $(RM) $@; \ \
+ HaskellCompilePreProcessing(module_isuf,module,isuf) @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ if [ -f $(@D)/$$iface ] ; then \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \ @@\
+ cp -p $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ chmod u+w $(@D)/$$iface ; \ @@\
+ fi ; \ @@\
+ set +e; \ @@\
+ echo $(HC) flags module_isuf -o module.o; \ @@\
+ $(HC) flags module_isuf -o module.o; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ $(RM) STAT ; \ @@\
+ $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ if [ -f STAT ] ; then $(MV) STAT module.STAT ; fi ; \ @@\
+ if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \ @@\
+ iface=`basename module_isuf .isuf`.hi ; \ @@\
+ $(UPDATEIFACE) $$iface $(@D)/$$iface ; \ @@\
+ $(RM) $(@D)/$$iface-SAVE ; \ @@\
+ fi \
+ HaskellCompilePostProcessing(module_isuf,module,isuf)
+
+#endif /* ! ChalmersHBC or GHC */
+\end{code}
+
+The default for the ``pre-'' and/or ``post-processing'' part (possibly
+swizzling around profiling/statistics files) is, of course, to do no
+such thing.
+\begin{code}
+#ifndef HaskellCompilePreProcessing
+#define HaskellCompilePreProcessing(module_isuf,module,isuf) /* nothing */
+#endif /* ! HaskellCompilePreProcessing */
+
+#ifndef HaskellCompilePostProcessing
+#define HaskellCompilePostProcessing(module_isuf,module,isuf) /* nothing */
+#endif /* ! HaskellCompilePostProcessing */
+\end{code}
+
+Now we just use the \tr{_body_*} thing above...
+\begin{code}
+#ifndef HaskellCompileWithSpecifiedFlags
+#define HaskellCompileWithSpecifiedFlags(module,isuf,flags) @@\
+module.o : module.isuf \
+_body_HaskellCompileWithSpecifiedFlags(module.isuf,module,isuf,flags)
+#endif /* HaskellCompileWithSpecifiedFlags */
+
+#ifndef HaskellCompileWithExtraFlags
+#define HaskellCompileWithExtraFlags(module,isuf,flags) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) flags)
+#endif /* HaskellCompileWithExtraFlags */
+
+#ifndef HaskellCompile
+#define HaskellCompile(module,isuf) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS))
+#endif /* HaskellCompile */
+\end{code}
+
+Asking for extra heap: the amount requested is the SEMI-SPACE size;
+the actual amount of heap memory used will be twice that.
+\begin{code}
+#ifndef HaskellCompileWithMoreHeapAndStack
+#define HaskellCompileWithMoreHeapAndStack(module,isuf,heapsize,stksize) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize) HaskellCompilerStkSize(stksize))
+#endif /* HaskellCompileWithMoreHeapAndStack */
+
+#ifndef HaskellCompileWithMoreHeap
+#define HaskellCompileWithMoreHeap(module,isuf,heapsize) @@\
+HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize))
+#endif /* HaskellCompileWithMoreHeap */
+\end{code}
+
+But we need those per-compiler HeapSize/StkSize/RunCpp macros...
+\begin{code}
+#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
+#define HaskellCompilerHeapSize(size) -Rmax-heapsize size
+#define HaskellCompilerStkSize(size) -Rmax-stksize size
+#define HaskellCompilerRunCpp() -cpp
+#define HaskellEndRTSFlags() /*none*/
+
+#elif HaveChalmersHBC == YES && UseChalmersHBC == YES
+#define HaskellCompilerHeapSize(size) CAT2(-H,size)
+#define HaskellCompilerStkSize(size) CAT2(-V,size)
+#define HaskellCompilerRunCpp() -M
+#define HaskellEndRTSFlags() -
+
+#else /* not GHC or HBC; assume nhc */
+#define HaskellCompilerHeapSize(size) CAT2(-H,size)
+#define HaskellCompilerStkSize(size) /*cant set stksize*/
+#define HaskellCompilerRunCpp() /*none*/
+#define HaskellEndRTSFlags() -
+
+#endif /* not GHC or HBC */
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-macros-scripts]{Processing scripts into ``executables''}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifndef ProgramScriptTarget
+#if HasExecableScripts /* can use #! */
+#define ProgramScriptTarget(prog,dst,src,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ cat src >> $@ @@\
+ chmod a+x $@
+#else
+#define ProgramScriptTarget(prog,dst,src,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ cat src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@
+#endif /* HasExecableScripts */
+#endif /* ProgramScriptTarget */
+\end{code}
+
+Create a target by running it through @msub@:
+\begin{code}
+#ifndef MsubTarget
+#define MsubTarget(dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(MSUB) flags src > dst
+#endif
+\end{code}
+
+@MsubProgramScriptTarget@: generate rules to create a script for an
+arbitrary program by running the input through @msub@. If
+@HasExecableScripts@ isn't @YES@, then make sure that the first line
+begins with a colon and write the script into a temp file, have the
+program execute that, and remove the temp file when done. Ugly ugly
+ugly... @prog@ must be a full pathname...
+\begin{code}
+#ifndef MsubProgramScriptTarget
+#if HasExecableScripts /* can use #! */
+#define MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ ${MSUB} flags src >> $@ @@\
+ chmod a+x $@
+#else
+#define MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+AllTarget(dst) @@\
+ExtraStuffToClean(dst) @@\
+dst:: src deplist @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ ${MSUB} flags src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@
+#endif /* HasExecableScripts */
+#endif /* MsubProgramScriptTarget */
+\end{code}
+
+For an @msub@ target that really slurps things out of the
+\tr{Makefile}, we delete it as part of \tr{make Makefile(s)}, so that
+it will be re-made.
+\begin{code}
+#ifndef MsubMakefileDependentProgramScriptTarget
+#define MsubMakefileDependentProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+MsubProgramScriptTarget(prog,dst,src,flags,deplist) @@\
+ @@\
+Makefile:: @@\
+ $(RM) dst
+#endif
+\end{code}
+
+\begin{code}
+#ifndef MsubScriptTarget
+#define MsubScriptTarget(dst,src,flags,deplist) @@\
+MsubProgramScriptTarget(${SHELL},dst,src,flags,deplist)
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-macros-bld-libs]{Linking modules/files into libraries}
+%* *
+%************************************************************************
+
+@NormalLibraryTarget@: generate rules to create a library.
+
+\begin{code}
+#ifndef NormalLibraryTarget
+#define NormalLibraryTarget(libname,objlist) @@\
+AllTarget(CAT2(lib,libname.a)) @@\
+ExtraStuffToClean(CAT2(lib,libname.a)) @@\
+CAT2(lib,libname.a):: objlist @@\
+ $(RM) $@ @@\
+ $(AR) $@ objlist @@\
+ $(RANLIB) $@
+#endif /* NormalLibraryTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-runtests]{Macros related to \tr{runtests} std target}
+%* *
+%************************************************************************
+
+Rules to do with standard @runtests@ target.
+
+\begin{code}
+#ifndef RuntestsTarget
+#define RuntestsTarget(depends) @@\
+runtests:: CAT2(runtest_,depends)
+#endif
+
+#ifndef RunStdTestTimeCmd
+#define RunStdTestTimeCmd /*none*/
+#endif
+
+#ifndef RunStdTest
+#define RunStdTest(name,prog,teststuff) @@\
+RuntestsTarget(name) @@\
+CAT2(runtest_,name):: @@\
+ @RunStdTestTimeCmd $(RUNSTDTEST) prog $(RUNSTDTEST_FLAGS) teststuff
+#endif /* RunStdTest */
+
+#ifndef AsPartOfTest
+#define AsPartOfTest(test,cmdline) @@\
+RuntestsTarget(test) @@\
+CAT2(runtest_,test):: @@\
+ cmdline
+#endif /* AsPartOfTest */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-install]{Macros related to \tr{install} std target}
+%* *
+%************************************************************************
+
+Run script through @msub@ with \tr{INSTALLING=1},
+putting result in a tmp file (don't mess w/ the @dst@ file here);
+install that tmp file in the right place.
+\begin{code}
+#ifndef InstallMsubbedScriptTarget
+#if HasExecableScripts /* can use #! */
+#define InstallMsubbedScriptTarget(prog,dst,src,installdir) @@\
+dst-tmp: src @@\
+ $(RM) $@ @@\
+ echo "#!"prog > $@ @@\
+ ${MSUB} INSTALLING=1 src >> $@ @@\
+ chmod a+x $@ @@\
+ @@\
+InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,) @@\
+install:: @@\
+ $(RM) dst-tmp
+#else
+#define InstallMsubbedScriptTarget(prog,dst,src,installdir) @@\
+dst-tmp: src @@\
+ $(RM) $@ @@\
+ echo \: > $@ @@\
+ echo 'x=/tmp/xx$$$$' >> $@ @@\
+ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\
+ ${MSUB} INSTALLING=1 src >> $@ @@\
+ echo EOF >> $@ @@\
+ echo prog '$$x' '$$@' >> $@ @@\
+ echo $(RM) '$$x' >> $@ @@\
+ chmod a+x $@ @@\
+ @@\
+InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,) @@\
+install:: @@\
+ $(RM) dst-tmp
+#endif /* HasExecableScripts */
+#endif /* InstallMsubbedScriptTarget */
+
+/*
+ INSTALLATION RULES. InstallTarget() should be a part of nearly
+ all of these, to add the target to the "install" rule.
+*/
+
+#ifndef InstallTarget
+#define InstallTarget(depends) @@\
+install:: CAT2(install_,depends)
+#endif
+
+#ifndef InstallDocTarget
+#define InstallDocTarget(depends) @@\
+install_docs:: CAT2(install_doc_,depends)
+#endif
+
+/*
+ Install a target specifying the flags to use. Many of the following
+ installation rules are instantiated as a particular expansion of this.
+*/
+
+#ifndef InstallTargetWithNameAndFlags
+#define InstallTargetWithNameAndFlags(target,destdir,new_name,flags) @@\
+InstallTarget(new_name) @@\
+CAT2(install_,new_name):: target @@\
+ $(INSTALL) -c flags target destdir/new_name
+#endif
+
+#ifndef InstallTargetWithFlags
+#define InstallTargetWithFlags(target,dest,flags) @@\
+InstallTargetWithNameAndFlags(target,dest,target,flags)
+#endif
+
+#ifndef InstallDocTargetWithFlags
+#define InstallDocTargetWithFlags(src,presuff,target,postsuff,dest,flags) @@\
+InstallDocTarget(CAT3(target,_,postsuff)) @@\
+CAT4(install_doc_,target,_,postsuff):: src.presuff @@\
+ $(INSTALL) -c flags src.presuff dest/target.postsuff
+#endif
+
+/*
+ Install a program
+*/
+
+#ifndef InstallBinaryTarget
+#define InstallBinaryTarget(program,dest) @@\
+InstallTargetWithFlags(program,dest,$(INSTBINFLAGS))
+#endif
+
+/* Install a setuid/setgid/etc program -- DELETED (partain)
+*/
+
+/*
+ Install an executable script
+*/
+
+#ifndef InstallScriptTarget
+#define InstallScriptTarget(script,dest) @@\
+InstallTargetWithFlags(script,dest,$(INSTSCRIPTFLAGS))
+#endif
+
+/*
+ Install a library (platform-dependent)
+*/
+
+#ifndef InstallLibraryTarget
+#define InstallLibraryTarget(libname,dest) @@\
+InstallTargetWithFlags(CAT2(lib,libname).a,dest,$(INSTLIBFLAGS)) @@\
+ ${RANLIB} dest/CAT2(lib,libname).a
+#endif
+
+/*
+ Install an include file
+*/
+
+#ifndef InstallIncludeTarget
+#define InstallIncludeTarget(file,dest) @@\
+InstallTargetWithFlags(file,dest,$(INSTINCFLAGS))
+#endif
+
+/*
+ Install a non-executable or data file (these are equivalent)
+*/
+
+#ifndef InstallDataTarget
+#define InstallDataTarget(file,dest) @@\
+InstallTargetWithFlags(file,dest,$(INSTDATAFLAGS))
+#endif
+
+/*
+ Install a set of non-executable files
+
+ DUMP THIS SOMETIME.
+*/
+
+#ifndef InstallMultNonExecTargets
+#define InstallMultNonExecTargets(rule,targets,dest) @@\
+CAT2(install_,rule):: rule @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in targets ;\ @@\
+ do \ @@\
+ echo $(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \ @@\
+ $(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \ @@\
+ done
+#endif
+
+/*
+ Install a man page.
+
+ THIS IS WRONG - rules in Jmakefiles don't have suffix!
+
+ file srcsuffix destdir dstsuffix ???
+*/
+
+#ifndef InstallManPageTarget
+#define InstallManPageTarget(file,destdir,suffix) @@\
+InstallDocTargetWithFlags(file,man,file,suffix,destdir,$(INSTMANFLAGS))
+#endif
+
+#ifndef InstallInfoFileTarget
+#define InstallInfoFileTarget(src,target,destdir) @@\
+InstallDocTargetWithFlags(src,info,target,info,destdir,$(INSTMANFLAGS))
+#endif
+
+#ifndef InstallLinkTarget
+#define InstallLinkTarget(target, linkto, dir) @@\
+InstallTarget(target) @@\
+CAT2(install_,target):: CAT2(install_,linkto) @@\
+ RemoveTarget(dir/target) @@\
+ ${LN} dir/linkto dir/target
+#endif
+
+/*
+ Fake install rules for things not installed anywhere
+*/
+
+#ifndef FakeInstallTarget
+#define FakeInstallTarget(target) @@\
+InstallTarget(target) @@\
+CAT2(install_,target):: target @@\
+ @echo target is not installed anywhere.
+#endif
+
+#ifndef FakeInstallLibrary
+#define FakeInstallLibrary(libname) @@\
+InstallTarget(CAT2(lib,libname).a) @@\
+CAT2(install_lib,libname).a:: CAT2(lib,libname).a @@\
+ @echo CAT2(lib,libname).a is not installed anywhere.
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-docs]{Macros related to \tr{docs} std target}
+%* *
+%************************************************************************
+
+Need rules just to make a man page or info file.
+
+\begin{code}
+#ifndef DocsTarget
+#define DocsTarget(depends) @@\
+docs:: depends
+#endif
+
+/* putting the InfoStuffNeededHere in semi-presumes that
+ LitDocRootTarget is only used once per directory (?)
+*/
+#ifndef LitDocRootTargetWithNamedOutput
+#define LitDocRootTargetWithNamedOutput(rootroot,rootext,rootout) @@\
+DocsTarget(rootroot.info rootroot.dvi) @@\
+ExtraStuffToClean(rootroot.info rootroot.dvi rootroot.texi rootroot.tex) @@\
+LitDependTarget(rootroot,rootext) @@\
+ @@\
+rootroot.info:: rootroot.texi @@\
+ RemoveTarget($@) @@\
+ $(MAKEINFO) $(MAKEINFOFLAGS) rootroot.texi \ @@\
+ && $(POSTMAKEINFO) rootroot.info @@\
+ @@\
+rootroot.dvi:: rootroot.tex @@\
+ RemoveTarget($@) @@\
+ $(LTX) rootroot.tex @@\
+ @@\
+rootroot.texi: rootout.itxi @@\
+ RemoveTarget($@) @@\
+ $(LIT2TEXI) -S $(LIT2TEXIFLAGS) -N rootroot.info -o rootroot.texi rootout.itxi @@\
+ @@\
+rootout.itxi: rootroot.rootext @@\
+ RemoveTarget($@) @@\
+ $(LIT2TEXI) -S -c $(LIT2TEXIFLAGS) -o rootout.itxi rootroot.rootext @@\
+ @@\
+rootroot.tex: rootout.itex @@\
+ RemoveTarget($@) @@\
+ $(LIT2LATEX) -S $(LIT2LATEXFLAGS) -o rootroot.tex rootout.itex @@\
+ @@\
+rootout.itex: rootroot.rootext @@\
+ RemoveTarget($@) @@\
+ $(LIT2LATEX) -S -c $(LIT2LATEXFLAGS) -o rootout.itex rootroot.rootext
+#endif /* LitDocRootTargetWithNamedOutput */
+
+#ifndef LitDocRootTarget
+#define LitDocRootTarget(rootroot,rootext) \
+LitDocRootTargetWithNamedOutput(rootroot,rootext,rootroot)
+#endif /* LitDocRootTarget */
+
+#ifndef VerbatimAndTibTarget
+#define VerbatimAndTibTarget(root) @@\
+VerbatimNeededHere(docs root.tex) @@\
+DocsTarget(root.dvi) @@\
+ExtraStuffToClean(root.dvi root.tex)
+#endif /* VerbatimAndTibTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-install-docs]{Macros related to \tr{install_docs} std target}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-cleaning]{Macros related to \tr{clean} (and \tr{veryclean}) std targets}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifndef ExtraStuffToClean
+#define ExtraStuffToClean(extra) @@\
+clean:: @@\
+ $(RM) extra
+#endif /* ExtraStuffToClean */
+
+#ifndef ExtraStuffToBeVeryClean
+#define ExtraStuffToBeVeryClean(extra) @@\
+veryclean:: @@\
+ $(RM) extra
+#endif /* ExtraStuffToBeVeryClean */
+
+#ifndef RemoveTarget
+#if RemoveTargetByMoving
+#define RemoveTarget(program) \
+$(RM) program; if [ -f program ]; then $(MV) program CAT2(program,~); fi
+#else
+#define RemoveTarget(program) $(RM) program
+#endif /* ! RemoveTargetByMoving */
+#endif /* RemoveTarget */
+/*
+ * CleanTarget - generate rules to remove any garbage files; the #* is here
+ * instead of in the definition of CLEAN_CMD because System V would treat a
+ * pound sign in the CLEAN_CMD variable as a comment.
+ */
+#ifndef CleanTarget
+#define CleanTarget() @@\
+clean:: @@\
+ $(CLEAN_CMD) \#*
+#endif /* CleanTarget */
+
+/*
+ * VeryCleanTarget - generate rules for "make veryclean"; the idea is
+ * that "make clean" does what "you almost always want" and "make
+ * veryclean" removes ALL generated files.
+ */
+#ifndef VeryCleanTarget
+#define VeryCleanTarget() @@\
+veryclean:: @@\
+ $(CLEAN_CMD) \#*
+#endif /* VeryCleanTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-tags]{Macros related to \tr{tags} std target}
+%* *
+%************************************************************************
+
+\begin{code}
+/* this should normally precede <>TagsTarget commands */
+/* those commands *append* to the TAGS file */
+#ifndef ClearTagsFile
+#define ClearTagsFile() @@\
+tags:: @@\
+ $(RM) TAGS; touch TAGS
+#endif
+
+/*
+ * CTagsTarget - generate rules to compute tags files for C source code.
+ * (specified as an arg)
+ * partain: we really expect "etags" to be used...
+ */
+#ifndef CTagsTarget
+#define CTagsTarget(srcs) @@\
+tags:: @@\
+ $(CTAGS) -a $(CTAGSFLAGS) srcs
+#endif /* CTagsTarget */
+
+/* Similarly for Perl and Haskell */
+#ifndef PerlTagsTarget
+#define PerlTagsTarget(srcs) @@\
+tags:: @@\
+ $(PERLTAGS) $(PERLTAGSFLAGS) srcs
+#endif /* PerlTagsTarget */
+
+#ifndef HsTagsTarget
+#define HsTagsTarget(srcs) @@\
+tags:: @@\
+ $(HSTAGS) $(HSTAGSFLAGS) srcs
+#endif /* HsTagsTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-Makefile]{Macros related to \tr{make Makefile}}
+%* *
+%************************************************************************
+
+@BuildMakefileTarget@: generate rules to build a \tr{Makefile} from a
+\tr{Jmakefile} (and, in the past, any special jmake flags). This is
+generally done automatically by the template or by any special
+Jmakefiles.
+
+\begin{code}
+#ifndef BuildMakefileTarget
+#define BuildMakefileTarget() @@\
+JmakeNeededHere(Makefile) @@\
+ @@\
+Makefile:: $(MYJCONFIGFILES) @@\
+ @@\
+Makefile:: @@\
+ -@if [ -f Makefile ]; then \ @@\
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ @@\
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) @@\
+ $(JRESTOREDEPS) @@\
+ @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi @@\
+ @chmod 444 Makefile @@\
+ @echo ==== The new Makefile is for\: ==== @@\
+ @$(MAKE) whoami || \ @@\
+ ( echo 'Putting old Makefile back (see Makefile.bad)...' && \ @@\
+ $(MV) Makefile Makefile.bad && \ @@\
+ $(MV) Makefile.bak Makefile ) @@\
+ @@\
+whoami:: @@\
+ @echo $(PROJECTNAME), version $(PROJECTVERSION) @@\
+ @echo project\: $(PROJECTLABEL)\; setup\: $(SETUPLABEL) @@\
+ @echo now building on a \`$(BUILDPLATFORM)\' host @@\
+ @echo hoping to run on a \`$(HOSTPLATFORM)\' host
+#endif /* BuildMakefileTarget */
+\end{code}
+
+@MakefileTarget@: generate rules to build a normal \tr{Makefile}.
+\begin{code}
+#ifndef MakefileTarget
+#define MakefileTarget() @@\
+BuildMakefileTarget()
+#endif /* MakefileTarget */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-MISC]{MISCELLANEOUS macros}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifndef GenerateOptionsMakeVars
+#define GenerateOptionsMakeVars(PGM,THINGS,AllProjectsPgmThings,PlatformPgmThings,ProjectPgmThings,SetupPgmThings) @@\
+CAT4(GLUED_,PGM,_,THINGS) = AllProjectsPgmThings PlatformPgmThings ProjectPgmThings SetupPgmThings $(CAT3(PGM,_,THINGS)) $(CAT4(EXTRA_,PGM,_,THINGS))
+#endif
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[mkworld-macros-subdir]{Sub-directories: things for std targets...}
+%* *
+%************************************************************************
+
+\subsubsection{@NamedTargetSubdirs@}
+
+Recursively make a series of steps.
+
+\begin{code}
+#ifndef NamedTargetSubdirs
+#define NamedTargetSubdirs(name,dirs,verb,flags,subname) @@\
+name:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ;\ @@\
+ do \ @@\
+ (cd $$i ; echo verb "in $(CURRENT_DIR)/$$i..."; \ @@\
+ $(MAKE) $(MFLAGS) flags subname); \ @@\
+ done
+#endif
+\end{code}
+
+\subsubsection{@NamedMakeSubdirs@}
+
+Generate rules to do makes in the given subdirectories. If you want
+@CDEBUGFLAGS@ passed along to subdirectories, provide a line like the
+following in the appropriate @Jmakefile@:
+
+\begin{verbatim}
+#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
+\end{verbatim}
+
+\begin{code}
+#ifndef NamedMakeSubdirs
+#define NamedMakeSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"making" name,PassCDebugFlags,all)
+#endif /* NamedMakeSubdirs */
+\end{code}
+
+\subsubsection{@DependSubdirs@}
+
+Generate rules to recursively compute dependencies as
+part of the make depend step.
+
+\begin{code}
+#ifndef DependSubdirs
+#define DependSubdirs(dirs) \
+NamedTargetSubdirs(depend,dirs,"making dependencies",/**/,depend)
+#endif /* DependSubdirs */
+\end{code}
+
+
+
+\subsubsection{@DoAllinSubdirs@}
+
+Generate rules to recursively \tr{make all}. The
+\tr{...MakeVarsForAll...} things can be set to have certain
+make-variable setting passed downwards.
+
+\begin{code}
+#ifndef ProjectMakeVarsForAllinSubdirs
+#define ProjectMakeVarsForAllinSubdirs /*none*/
+#endif
+
+#ifndef SetupMakeVarsForAllinSubdirs
+#define SetupMakeVarsForAllinSubdirs /*none*/
+#endif
+
+#ifndef DoAllinSubdirs
+#define DoAllinSubdirs(dirs) \
+NamedTargetSubdirs(all,dirs,"making all",ProjectMakeVarsForAllinSubdirs SetupMakeVarsForAllinSubdirs,all)
+#endif /* DoAllinSubdirs */
+\end{code}
+
+\subsubsection{@DoDocsinSubdirs@}
+Generate rules to recursively \tr{make docs}.
+\begin{code}
+#ifndef DoDocsinSubdirs
+#define DoDocsinSubdirs(dirs) \
+NamedTargetSubdirs(docs,dirs,"making docs",/*no make flags*/,docs)
+#endif /* DoDocsinSubdirs */
+\end{code}
+
+\subsubsection{@RunTestsSubdirs@}
+
+Generate rules to recursively \tr{make runtests}.
+
+\begin{code}
+#ifndef ProjectMakeVarsForRunTestsinSubdirs
+#define ProjectMakeVarsForRunTestsinSubdirs /*none*/
+#endif
+
+#ifndef SetupMakeVarsForRunTestsinSubdirs
+#define SetupMakeVarsForRunTestsinSubdirs /*none*/
+#endif
+
+#ifndef RunTestsSubdirs
+#define RunTestsSubdirs(dirs) \
+NamedTargetSubdirs(runtests,dirs,"running tests",ProjectMakeVarsForRunTestsinSubdirs SetupMakeVarsForRunTestsinSubdirs,runtests)
+#endif /* RunTestsSubdirs */
+\end{code}
+
+\subsubsection{@InstallSubdirs@}
+Generate rules to recursively \tr{make install}.
+\begin{code}
+#ifndef InstallSubdirs
+#define InstallSubdirs(dirs) \
+NamedTargetSubdirs(install,dirs,"installing",INSTROOT='$(INSTROOT)',install)
+#endif /* InstallSubdirs */
+\end{code}
+
+\subsubsection{@InstallDocsSubdirs@}
+Generate rules to recursively \tr{make install_docs}.
+\begin{code}
+#ifndef InstallDocsSubdirs
+#define InstallDocsSubdirs(dirs) \
+NamedTargetSubdirs(install_docs,dirs,"installing documentation",INSTROOT='$(INSTROOT)',install_docs)
+#endif /* InstallDocsSubdirs */
+\end{code}
+
+\subsubsection{@CleanSubdirs@}
+Generate rules to recursively \tr{make clean}.
+\begin{code}
+#ifndef NamedCleanSubdirs
+#define NamedCleanSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"cleaning",RM='$(RM)',clean)
+#endif /* NamedCleanSubdirs */
+
+#ifndef CleanSubdirs
+#define CleanSubdirs(dirs) \
+NamedCleanSubdirs(clean,dirs)
+#endif
+\end{code}
+
+\subsubsection{@VeryCleanSubdirs@}
+Generate rules to recursively \tr{make veryclean}.
+\begin{code}
+#ifndef NamedVeryCleanSubdirs
+#define NamedVeryCleanSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"being veryclean",RM='$(RM)',veryclean)
+#endif /* NamedCleanSubdirs */
+
+#ifndef VeryCleanSubdirs
+#define VeryCleanSubdirs(dirs) \
+NamedVeryCleanSubdirs(veryclean,dirs)
+#endif
+\end{code}
+
+\subsubsection{@TagSubdirs@}
+Generate rules to recursively \tr{make tags} (create TAGS files).
+\begin{code}
+#ifndef NamedTagSubdirs
+#define NamedTagSubdirs(name,dirs) \
+NamedTargetSubdirs(name,dirs,"making tags",,tags)
+#endif /* TagSubdirs */
+
+#ifndef TagSubdirs
+#define TagSubdirs(dirs) \
+NamedTagSubdirs(tags,dirs)
+#endif
+\end{code}
+
+\subsubsection{@MakeMakeSubdirs@}
+
+Generate rules to recursively recreate Makefiles as part of the
+specified step in the build. If @$(TOP)@ is set to an absolute
+path, don't prepend the @../@ prefix. This makes running things
+outside of the source tree much easier.
+
+\begin{code}
+#ifndef MakeMakeSubdirs
+#define MakeMakeSubdirs(dirs,target) @@\
+target:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ;\ @@\
+ do \ @@\
+ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ @@\
+ case "$$i" in \ @@\
+ ./?*/?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \ @@\
+ ./?*/?*/?*) newtop=../../../ sub=subsubsub;; \ @@\
+ ./?*/?*) newtop=../../ sub=subsub;; \ @@\
+ ./?*) newtop=../ sub=sub;; \ @@\
+ */?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \ @@\
+ */?*/?*) newtop=../../../ sub=subsubsub;; \ @@\
+ */?*) newtop=../../ sub=subsub;; \ @@\
+ *) newtop=../ sub=sub;; \ @@\
+ esac; \ @@\
+ case "$(TOP)" in \ @@\
+ /?*) newtop= upprefix= ;; \ @@\
+ *) upprefix=../ ;; \ @@\
+ esac; \ @@\
+ $(MAKE) $${sub}dirMakefiles UPPREFIX=$$upprefix NEWTOP=$$newtop \ @@\
+ MAKEFILE_SUBDIR=$$i NEW_CURRENT_DIR=$(CURRENT_DIR)/$$i;\ @@\
+ done
+#endif /* MakeMakeSubdirs */
+\end{code}
+
+\subsubsection{@MakeNsubdirMakefiles@}
+
+Generate rules to create sub Makefiles.
+
+\begin{code}
+#ifndef MakeNsubdirMakefiles
+#define MakeNsubdirMakefiles() @@\
+subdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles @@\
+ @@\
+subsubsubsubdirMakefiles: @@\
+ $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak @@\
+ -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \ @@\
+ echo " $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
+ $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
+ else exit 0; fi @@\
+ cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
+ $(NEWTOP)$(JRESTOREDEPS); \ @@\
+ $(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles
+#endif /* MakeNsubdirMakefiles */
+\end{code}
+
+\subsubsection{@MakefileSubdirs@}
+
+Generate rules to create \tr{Makefiles}.
+
+\begin{code}
+#ifndef MakefileSubdirs
+#define MakefileSubdirs(dirs) @@\
+MakeMakeSubdirs(dirs,Makefiles) @@\
+ @@\
+MakeNsubdirMakefiles()
+#endif /* MakefileSubdirs */
+\end{code}
+
+\begin{code}
+#ifndef MakeDirectories
+#define MakeDirectories(step,dirs) @@\
+step:: @@\
+ $(MKDIRHIER) dirs
+#endif
+\end{code}
+
+\begin{code}
+#ifndef LinkDirectories
+#define LinkDirectories(step,dirs,todir) @@\
+step:: @@\
+ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\
+ for i in dirs ; \ @@\
+ do \ @@\
+ echo "linking $$i to" todir; \ @@\
+ $(LNDIR) todir $$i; \ @@\
+ done
+#endif
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-DEF.jm b/web/glasgow/lit2x-0.16/mkworld/plat-DEF.jm
new file mode 100644
index 0000000000..bcdbb93eea
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-DEF.jm
@@ -0,0 +1,27 @@
+# line 8 "plat-DEF.ljm"
+#ifndef OSMajorVersion
+#define OSMajorVersion 0
+#endif
+#ifndef OSMinorVersion
+#define OSMinorVersion 0
+#endif
+
+#ifndef HasExecableScripts
+#define HasExecableScripts YES /* can execute scripts with #! */
+#endif
+
+#ifndef ConstructMFLAGS
+#define ConstructMFLAGS NO /* build MFLAGS from MAKEFLAGS */
+#endif
+#if ConstructMFLAGS
+MFLAGS = -$(MAKEFLAGS)
+#endif
+
+#ifndef BourneShell /* to force shell in Makefile */
+#define BourneShell /bin/sh
+#endif
+SHELL = BourneShell
+# line 35 "plat-DEF.ljm"
+#ifndef CppHaveSysVishTimesH
+#define CppHaveSysVishTimesH /*nothing*/
+#endif
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-DEF.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-DEF.ljm
new file mode 100644
index 0000000000..a4d1051222
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-DEF.ljm
@@ -0,0 +1,38 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-GEN]{{\em Defaults} for platform-specific things}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifndef OSMajorVersion
+#define OSMajorVersion 0
+#endif
+#ifndef OSMinorVersion
+#define OSMinorVersion 0
+#endif
+
+#ifndef HasExecableScripts
+#define HasExecableScripts YES /* can execute scripts with #! */
+#endif
+
+#ifndef ConstructMFLAGS
+#define ConstructMFLAGS NO /* build MFLAGS from MAKEFLAGS */
+#endif
+#if ConstructMFLAGS
+MFLAGS = -$(MAKEFLAGS)
+#endif
+
+#ifndef BourneShell /* to force shell in Makefile */
+#define BourneShell /bin/sh
+#endif
+SHELL = BourneShell
+\end{code}
+
+Have System V-ish \tr{times.h}, with \tr{times} routine, rather than
+Berkeley-style \tr{time.h} with \tr{ftime}, etc.
+\begin{code}
+#ifndef CppHaveSysVishTimesH
+#define CppHaveSysVishTimesH /*nothing*/
+#endif
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.jm b/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.jm
new file mode 100644
index 0000000000..4ccac86ea8
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.jm
@@ -0,0 +1,50 @@
+# line 1 "plat-TRIGGERS.ljm"
+# line 29 "plat-TRIGGERS.ljm"
+#ifdef sun
+#define PlatformFile plat-sun.jm
+#define PlatformIncludeFile <plat-sun.jm>
+
+#undef sun
+#define SunArchitecture
+#endif /* sun */
+# line 45 "plat-TRIGGERS.ljm"
+#ifdef linux
+#define PlatformFile plat-linux.jm
+#define PlatformIncludeFile <plat-linux.jm>
+
+#undef linux
+#define LinuxArchitecture
+#endif /* linux */
+# line 61 "plat-TRIGGERS.ljm"
+#if defined(__alpha) && defined(__osf__)
+#define PlatformFile plat-alpha.jm
+#define PlatformIncludeFile <plat-alpha.jm>
+
+#undef __alpha
+#undef __osf__
+#define AlphaArchitecture
+#endif /* alpha */
+# line 85 "plat-TRIGGERS.ljm"
+#ifdef mipsriscos
+#define PlatformFile plat-mipsriscos.jm
+#define PlatformIncludeFile <plat-mipsriscos.jm>
+
+#undef mipsriscos
+#undef mips
+#define MipsRiscosArchitecture /* for OS type */
+#define MipsArchitecture /* for chipset type */
+/* now a dubious HostPlatform definition (there are various "mips" machines) ... */
+
+/* ToDo: I admit these are done to suit the Glasgow /bin/arch */
+/* It should probably be "umips" or "umipse[bl]", as appropriate */
+#ifdef SYSTYPE_SYSV
+#define HostPlatform mips3000
+#else
+#define HostPlatform mips
+#endif
+#endif /* mipsriscos */
+# line 258 "plat-TRIGGERS.ljm"
+#ifndef PlatformIncludeFile
+#define PlatformFile could-not-determine-the-platform-from-trigger-symbols
+#define PlatformIncludeFile PlatformFile
+#endif
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.ljm
new file mode 100644
index 0000000000..74fbc927d9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-TRIGGERS.ljm
@@ -0,0 +1,290 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-TRIGGERS]{Detecting the ``trigger symbol'' for this platform}
+%* *
+%************************************************************************
+
+See the end of this section for how to add support for another platform.
+
+Note: Only a handful of platforms have been tested with these
+configuration files (ToDo).
+
+You do basically three things here:
+\begin{enumerate}
+\item
+Set @PlatformFile@, etc.
+\item
+Turn {\em off} any vendor-supplied ``this-is-a-BLAH'' symbol(s).
+\item
+Turn {\em on} our own ``this-is-a-FOO-Architecture'' symbol(s).
+\end{enumerate}
+
+%************************************************************************
+%* *
+\subsection[trigger-Sun]{Trigger stuff for Suns}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifdef sun
+#define PlatformFile plat-sun.jm
+#define PlatformIncludeFile <plat-sun.jm>
+
+#undef sun
+#define SunArchitecture
+#endif /* sun */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[trigger-Linux]{Trigger stuff for Linux}
+%* *
+%************************************************************************
+
+\begin{code}
+#ifdef linux
+#define PlatformFile plat-linux.jm
+#define PlatformIncludeFile <plat-linux.jm>
+
+#undef linux
+#define LinuxArchitecture
+#endif /* linux */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[trigger-Alpha]{Trigger stuff for DEC Alpha running OSF1}
+%* *
+%************************************************************************
+
+\begin{code}
+#if defined(__alpha) && defined(__osf__)
+#define PlatformFile plat-alpha.jm
+#define PlatformIncludeFile <plat-alpha.jm>
+
+#undef __alpha
+#undef __osf__
+#define AlphaArchitecture
+#endif /* alpha */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[trigger-MIPS-RiscOS]{Trigger stuff for MIPS machines running RISCos}
+%* *
+%************************************************************************
+
+OLD: OLD: OLD:
+
+@mipsriscos@ used instead of @riscos@ because another company (Acorn
+Computers Ltd in the UK) has a RISC OS... MIPS RISC/os cpp has no
+unique symbol: build @jmake@ with
+@BOOTSTRAPCFLAGS=-Dmipsriscos@
+
+\begin{code}
+#ifdef mipsriscos
+#define PlatformFile plat-mipsriscos.jm
+#define PlatformIncludeFile <plat-mipsriscos.jm>
+
+#undef mipsriscos
+#undef mips
+#define MipsRiscosArchitecture /* for OS type */
+#define MipsArchitecture /* for chipset type */
+/* now a dubious HostPlatform definition (there are various "mips" machines) ... */
+
+/* ToDo: I admit these are done to suit the Glasgow /bin/arch */
+/* It should probably be "umips" or "umipse[bl]", as appropriate */
+#ifdef SYSTYPE_SYSV
+#define HostPlatform mips3000
+#else
+#define HostPlatform mips
+#endif
+#endif /* mipsriscos */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[triggers-UNTESTED]{Untested trigger stuff for other machines}
+%* *
+%************************************************************************
+
+COMPLETELY UNTESTED (and so commented out):
+
+\begin{pseudocode}
+#ifdef ultrix
+#define PlatformIncludeFile <ultrix.cf>
+#define PlatformFile ultrix.cf
+#ifdef vax
+#undef vax
+#define VaxArchitecture
+/* hypothetical HostPlatform; we do not have one */
+#define HostPlatform vax
+#endif /* vax */
+#ifdef mips
+#undef mips
+#define MipsArchitecture
+/* hypothetical HostPlatform; we do not have one */
+#define HostPlatform pmax
+#endif /* mips */
+#undef ultrix
+#define UltrixArchitecture
+#endif /* ultrix */
+
+#if defined(vax) && !defined(UltrixArchitecture)
+#define PlatformIncludeFile <bsd.cf>
+#define PlatformFile bsd.cf
+#undef vax
+#define VaxArchitecture
+#endif
+\end{pseudocode}
+
+\begin{pseudocode}
+#ifdef hpux
+#define PlatformIncludeFile <hp.cf>
+#define PlatformFile hp.cf
+#undef hpux
+#define HPArchitecture
+#endif /* hpux */
+
+#ifdef att
+#define PlatformIncludeFile <att.cf>
+#define PlatformFile att.cf
+#undef att
+#define ATTArchitecture
+#endif /* att */
+
+#ifdef apollo
+#define PlatformIncludeFile <apollo.cf>
+#define PlatformFile apollo.cf
+#undef apollo
+#define ApolloArchitecture
+#endif /* apollo */
+
+#ifdef sony
+#define PlatformIncludeFile <sony.cf>
+#define PlatformFile sony.cf
+#undef sony
+#define SonyArchitecture
+#endif /* sony */
+
+#ifdef M4310
+#define PlatformIncludeFile <pegasus.cf>
+#define PlatformFile pegasus.cf
+#undef M4310
+#define PegasusArchitecture
+#endif /* M4310 */
+
+#ifdef M4330
+#define PlatformIncludeFile <m4330.cf>
+#define PlatformFile m4330.cf
+#undef M4330
+#define M4330Architecture
+#endif /* M4330 */
+
+#ifdef macII
+/* A/UX cpp has no unique symbol: build jmake with BOOTSTRAPCFLAGS=-DmacII */
+#define PlatformIncludeFile <macII.cf>
+#define PlatformFile macII.cf
+#undef macII
+#define MacIIArchitecture
+#endif /* macII */
+
+#ifdef CRAY
+#define PlatformIncludeFile <cray.cf>
+#define PlatformFile cray.cf
+#undef cray
+#undef CRAY
+#define CrayArchitecture
+#endif /* CRAY */
+
+#ifdef sgi
+#define PlatformIncludeFile <sgi.cf>
+#define PlatformFile sgi.cf
+#undef sgi
+#define SGIArchitecture
+#undef mips
+#define MipsArchitecture
+#endif
+
+#ifdef stellar
+#define PlatformIncludeFile <stellar.cf>
+#define PlatformFile stellar.cf
+#undef stellar
+#define StellarArchitecture
+#endif
+
+/*
+ * A convenience for people running on rt's since they define ibm032, and for
+ * people running AIX (note that AOS will no longer be supported by IBM).
+ */
+#if defined(ibm032) && !defined(ibm)
+#define ibm
+#endif
+
+#if defined(aix) && !defined(ibm)
+#define ibm
+#endif
+
+#if defined(ibm)
+#define PlatformIncludeFile <ibm.cf>
+#define PlatformFile ibm.cf
+#undef ibm
+#define IBMArchitecture
+#ifdef i386
+#undef i386
+#define PS2Architecture
+#endif
+#ifdef ibm032
+#undef ibm032
+#define RtArchitecture
+#endif
+#ifdef aix
+#undef aix
+#define AIXArchitecture
+#endif
+#endif /* ibm */
+\end{pseudocode}
+
+%************************************************************************
+%* *
+\subsection[triggers-failed]{If no trigger symbol worked...}
+%* *
+%************************************************************************
+
+We don't allow guessing at the platform: this will bomb gruesomely in
+short order; it might mean that @BOOTSTRAPCFLAGS@ was not set when
+building @jmake@.
+\begin{code}
+#ifndef PlatformIncludeFile
+#define PlatformFile could-not-determine-the-platform-from-trigger-symbols
+#define PlatformIncludeFile PlatformFile
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[triggers-adding-platform]{To add support for another platform...}
+%* *
+%************************************************************************
+
+\begin{enumerate}
+\item
+Identify a machine-specific CPP (``trigger'') symbol. If your preprocessor
+doesn't have any built in, you'll need to add the symbol to the
+@cpp_argv@ table in \tr{utils/jmake/jmake.c} and rebuild @jmake@ with the
+@BOOTSTRAPCFLAGS@ variable set (see the macII for an example).
+
+\item
+Add all machine-specific CPP symbols (either defined by you or by
+the preprocessor or compiler) to the @predefs@ table in
+@util/makedepend/main.c@.
+
+\item
+Put a new \tr{#ifdef} block above that defines @PlatformIncludeFile@,
+@PlatformFile@, etc., for your new platform and then @#undefs@ the
+machine-specific preprocessor symbols (to avoid problems with file
+names).
+
+\item
+Create suitable \tr{*.jm} files (or ``literate'' equivalents).
+\end{enumerate}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-alpha.jm b/web/glasgow/lit2x-0.16/mkworld/plat-alpha.jm
new file mode 100644
index 0000000000..47c16c49d6
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-alpha.jm
@@ -0,0 +1,20 @@
+# line 8 "plat-alpha.ljm"
+#define HostPlatform alpha
+
+#define OSName OSF1
+#define OSMajorVersion 1
+#define OSMinorVersion 2
+
+#define HasSysVishArAndRanlib YES
+
+#define CppHaveSysVishTimesH -DHAVE_SYSV_ISH_TIMES_H
+
+BUILDPLATFORM=HostPlatform
+
+/* Whenever we run the "std C compiler", give it this flag
+ (not really platform-ish, but a convenient place to put it)
+*/
+#define PlatformCcOpts -ansi -Wall /* full ANSI, please */
+
+/* temp: just for debugging */
+#define GhcNormalHighLevelAsmDefaultOpts ('-ansi')
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-alpha.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-alpha.ljm
new file mode 100644
index 0000000000..e06129c19b
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-alpha.ljm
@@ -0,0 +1,27 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-alpha]{Platform configuration stuff for DEC Alpha}
+%* *
+%************************************************************************
+
+\begin{code}
+#define HostPlatform alpha
+
+#define OSName OSF1
+#define OSMajorVersion 1
+#define OSMinorVersion 2
+
+#define HasSysVishArAndRanlib YES
+
+#define CppHaveSysVishTimesH -DHAVE_SYSV_ISH_TIMES_H
+
+BUILDPLATFORM=HostPlatform
+
+/* Whenever we run the "std C compiler", give it this flag
+ (not really platform-ish, but a convenient place to put it)
+*/
+#define PlatformCcOpts -ansi -Wall /* full ANSI, please */
+
+/* temp: just for debugging */
+#define GhcNormalHighLevelAsmDefaultOpts ('-ansi')
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-linux.jm b/web/glasgow/lit2x-0.16/mkworld/plat-linux.jm
new file mode 100644
index 0000000000..56969a3aab
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-linux.jm
@@ -0,0 +1,26 @@
+# line 11 "plat-linux.ljm"
+#undef i386 /* move to trigger file? (ToDo) */
+
+#define iX86Architecture YES
+#define i486Architecture YES
+
+#define HostPlatform i486
+
+#define LinuxOSPlatform YES
+#define OSName Linux 0.99
+#define OSMajorVersion 0
+#define OSMinorVersion 99
+#define HaveGcc YES /* nothing else on linux... */
+
+BUILDPLATFORM=HostPlatform
+
+/* Whenever we run the "std C compiler", give it this flag */
+#define PlatformCcOpts -m486
+
+/*-----------------------------------------------------------------------------
+ Added by simonm...
+-----------------------------------------------------------------------------*/
+
+#define MakeCmd make -r /* make ignores implicit rules */
+
+/* #define UseFlexForLexCmd we've only got flex on Linux */
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-linux.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-linux.ljm
new file mode 100644
index 0000000000..d176614831
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-linux.ljm
@@ -0,0 +1,36 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-linus]{Linux-specific configuration stuff}
+%* *
+%************************************************************************
+
+[This file prepared by Andr\'e Santos, the Linux Functional
+Programming King (andre\@dcs.glasgow.ac.uk).]
+
+\begin{code}
+#undef i386 /* move to trigger file? (ToDo) */
+
+#define iX86Architecture YES
+#define i486Architecture YES
+
+#define HostPlatform i486
+
+#define LinuxOSPlatform YES
+#define OSName Linux 0.99
+#define OSMajorVersion 0
+#define OSMinorVersion 99
+#define HaveGcc YES /* nothing else on linux... */
+
+BUILDPLATFORM=HostPlatform
+
+/* Whenever we run the "std C compiler", give it this flag */
+#define PlatformCcOpts -m486
+
+/*-----------------------------------------------------------------------------
+ Added by simonm...
+-----------------------------------------------------------------------------*/
+
+#define MakeCmd make -r /* make ignores implicit rules */
+
+/* #define UseFlexForLexCmd we've only got flex on Linux */
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.jm b/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.jm
new file mode 100644
index 0000000000..472a264fa7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.jm
@@ -0,0 +1,51 @@
+# line 50 "plat-mipsriscos.ljm"
+/*
+ SET VERSION NUMBERS BEFORE MAKING MAKEFILES
+*/
+
+#define OSMajorVersion 4
+#define OSMinorVersion 51
+
+#define CCompilerMajorVersion 2
+#define CCompilerMinorVersion 11
+
+
+#define BootstrapCFlags -Dmipsriscos
+
+/*
+ For BSD environment, need -ltermcap for v?printf. It's not in
+ the BSD C library! (Yet.)
+*/
+
+#define InstallCmd /etc/mipsinstall
+#define InstFileFlags -f
+
+#ifndef UsrLibDir
+#if SystemV
+#define UsrLibDir /usr/lib
+#else
+#define UsrLibDir /usr/bsd43/usr/lib
+#endif
+#endif
+
+#ifndef IncludeRoot
+#if SystemV
+#define IncludeRoot /usr/include
+#else
+#define IncludeRoot /usr/include/bsd43
+#endif
+#endif
+
+#define HasVarargs YES
+/*
+ Make sure to use signal semantics that are consistent with
+ the compilation environment.
+*/
+#if SystemV
+#define HasVoidSignalReturn YES
+#else
+#define HasVoidSignalReturn NO
+#endif
+
+/* does this work? or can it be done better? ToDo */
+BUILDPLATFORM=HostPlatform
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.ljm
new file mode 100644
index 0000000000..1bb5496856
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-mipsriscos.ljm
@@ -0,0 +1,100 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-mipsriscos]{Configuration stuff for MIPS machines running RISCos}
+%* *
+%************************************************************************
+
+Derived from the Paul DuBois's configuration stuff.
+
+NOTES:
+
+The MIPS RISC/os modifications are for MIPS machines running RISC/os 4.0
+or later.
+
+To make makefiles for RISC/os you MUST set your environment
+variable JMAKEINCLUDE:
+ setenv JMAKEINCLUDE "-I. -Dmipsriscos -DSYSTYPE_SYSV"
+ (or) setenv JMAKEINCLUDE "-I. -Dmipsriscos -DSYSTYPE_BSD"
+as appropriate. Cpp does not set these on RISC/os; cc does, but cc is not used
+with jmake.
+
+For RISC/os it is important that the compiler, linker, include files and
+libraries be compatible with each other. This can mostly be taken care of
+by specifying the -systype {sysv,bsd43} option in the definition of CcCmd,
+which will alert the compiler which versions of itself, the linker and
+libraries are to be used, and for the most part, the proper include files.
+This works whether your PATH setting causes /bin/cc or /usr/bsd43/bin/cc
+to be found first. (-systype cannot be specified in StandardCppDefines,
+because those get passed to makedepend, and makedepend gets confused
+because -systype takes a following argument.)
+
+If installed versions of jmake or makedepend are used, it is important
+that they have been compiled in the same environment as that used to
+compile this project, or you will get sysv/bsd conflicts. It may be
+best to compile them for both environments and install in /usr/bin and
+/bsd43/usr/bin as appropriate.
+
+The compiled version of makedepend works properly subject to the above
+caveat, and is much faster than the script version. The script version
+(define UseCCMakeDepend) always works and needs no special hacking to know
+about compilation environment, but it's slower. It also generates warnings
+about "--" and -O which can be ignored. util/makedepend/Jmakefile was hacked
+from the X11R4 release to recognize how to set INCLUDEDIR properly for RISC/os.
+
+The Jmakefiles contain commands to format the man pages and install them as
+required; however since RISC/os does not include nroff this will typically
+not be effective. If you have the BSD or DWB packages installed, you may
+be in better shape.
+
+\begin{code}
+/*
+ SET VERSION NUMBERS BEFORE MAKING MAKEFILES
+*/
+
+#define OSMajorVersion 4
+#define OSMinorVersion 51
+
+#define CCompilerMajorVersion 2
+#define CCompilerMinorVersion 11
+
+
+#define BootstrapCFlags -Dmipsriscos
+
+/*
+ For BSD environment, need -ltermcap for v?printf. It's not in
+ the BSD C library! (Yet.)
+*/
+
+#define InstallCmd /etc/mipsinstall
+#define InstFileFlags -f
+
+#ifndef UsrLibDir
+#if SystemV
+#define UsrLibDir /usr/lib
+#else
+#define UsrLibDir /usr/bsd43/usr/lib
+#endif
+#endif
+
+#ifndef IncludeRoot
+#if SystemV
+#define IncludeRoot /usr/include
+#else
+#define IncludeRoot /usr/include/bsd43
+#endif
+#endif
+
+#define HasVarargs YES
+/*
+ Make sure to use signal semantics that are consistent with
+ the compilation environment.
+*/
+#if SystemV
+#define HasVoidSignalReturn YES
+#else
+#define HasVoidSignalReturn NO
+#endif
+
+/* does this work? or can it be done better? ToDo */
+BUILDPLATFORM=HostPlatform
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-sun.jm b/web/glasgow/lit2x-0.16/mkworld/plat-sun.jm
new file mode 100644
index 0000000000..7c4a98b539
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-sun.jm
@@ -0,0 +1,32 @@
+# line 8 "plat-sun.ljm"
+#define SunOSPlatform YES /* set to NO if not running SunOS */
+#define OSName SunOS 4.1
+#define OSMajorVersion 4
+#define OSMinorVersion 1
+
+#if OSMajorVersion >=4 && OSMinorVersion >= 1
+#define ConstructMFLAGS 1
+#endif
+
+#if OSMajorVersion >= 4
+#define HasSunOSSharedLibraries YES
+#endif
+
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#undef sparc
+#undef __sparc
+#undef __sparc__
+
+#define SparcArchitecture
+/* HostPlatform should probably be "sparc" but this suits Glasgow /bin/arch */
+#define HostPlatform sun4
+
+#else /* ! sparc */
+
+/* OK, a wild guess ... */
+#define m68kArchitecture
+#define HostPlatform sun3
+
+#endif /* ! sparc */
+
+BUILDPLATFORM=HostPlatform
diff --git a/web/glasgow/lit2x-0.16/mkworld/plat-sun.ljm b/web/glasgow/lit2x-0.16/mkworld/plat-sun.ljm
new file mode 100644
index 0000000000..1b11184366
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/plat-sun.ljm
@@ -0,0 +1,39 @@
+%************************************************************************
+%* *
+\section[mkworld-plat-sun]{Sun-specific configuration stuff}
+%* *
+%************************************************************************
+
+\begin{code}
+#define SunOSPlatform YES /* set to NO if not running SunOS */
+#define OSName SunOS 4.1
+#define OSMajorVersion 4
+#define OSMinorVersion 1
+
+#if OSMajorVersion >=4 && OSMinorVersion >= 1
+#define ConstructMFLAGS 1
+#endif
+
+#if OSMajorVersion >= 4
+#define HasSunOSSharedLibraries YES
+#endif
+
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#undef sparc
+#undef __sparc
+#undef __sparc__
+
+#define SparcArchitecture
+/* HostPlatform should probably be "sparc" but this suits Glasgow /bin/arch */
+#define HostPlatform sun4
+
+#else /* ! sparc */
+
+/* OK, a wild guess ... */
+#define m68kArchitecture
+#define HostPlatform sun3
+
+#endif /* ! sparc */
+
+BUILDPLATFORM=HostPlatform
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/site-DEF.jm b/web/glasgow/lit2x-0.16/mkworld/site-DEF.jm
new file mode 100644
index 0000000000..4e9fab42a9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/site-DEF.jm
@@ -0,0 +1,45 @@
+# line 1 "site-DEF.ljm"
+# line 8 "site-DEF.ljm"
+/* TopDir and CurDir likely defined on command line */
+#ifndef TopDir
+#define TopDir .
+#endif
+TOP = TopDir
+
+#ifndef TopDirPwd
+#define TopDirPwd /
+#endif
+TOP_PWD = TopDirPwd /* absolute pathname of TOP */
+
+#ifndef CurDir
+#define CurDir .
+#endif
+CURRENT_DIR = CurDir
+
+#ifndef TmpDir /* I do not know why this was /usr/tmp */
+#define TmpDir /tmp
+#endif
+TMPDIR = TmpDir /* temporary files */
+
+#ifndef BootstrapCFlags
+#define BootstrapCFlags /*none*/
+#endif
+BOOTSTRAPCFLAGS = BootstrapCFlags /* set if cpp doesn't have uniq sym */
+# line 36 "site-DEF.ljm"
+#ifndef ManDirectoryRoot
+#define ManDirectoryRoot /usr/man
+#endif
+
+#ifndef DefaultInfoPath
+#define DefaultInfoPath /usr/local/lib/info:.
+#endif
+
+#ifndef IncludeTestDirsInBuild
+#define IncludeTestDirsInBuild NO
+#endif
+
+/* Misc. misc. */
+
+#ifndef RemoveTargetByMoving
+#define RemoveTargetByMoving NO /* affects Jmake.rules */
+#endif
diff --git a/web/glasgow/lit2x-0.16/mkworld/site-DEF.ljm b/web/glasgow/lit2x-0.16/mkworld/site-DEF.ljm
new file mode 100644
index 0000000000..368542dea0
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/site-DEF.ljm
@@ -0,0 +1,53 @@
+%************************************************************************
+%* *
+\section[mkworld-site-GEN]{{\em Defaults} for site-selectable things}
+%* *
+%************************************************************************
+
+\begin{code}
+/* TopDir and CurDir likely defined on command line */
+#ifndef TopDir
+#define TopDir .
+#endif
+TOP = TopDir
+
+#ifndef TopDirPwd
+#define TopDirPwd /
+#endif
+TOP_PWD = TopDirPwd /* absolute pathname of TOP */
+
+#ifndef CurDir
+#define CurDir .
+#endif
+CURRENT_DIR = CurDir
+
+#ifndef TmpDir /* I do not know why this was /usr/tmp */
+#define TmpDir /tmp
+#endif
+TMPDIR = TmpDir /* temporary files */
+
+#ifndef BootstrapCFlags
+#define BootstrapCFlags /*none*/
+#endif
+BOOTSTRAPCFLAGS = BootstrapCFlags /* set if cpp doesn't have uniq sym */
+\end{code}
+
+\begin{code}
+#ifndef ManDirectoryRoot
+#define ManDirectoryRoot /usr/man
+#endif
+
+#ifndef DefaultInfoPath
+#define DefaultInfoPath /usr/local/lib/info:.
+#endif
+
+#ifndef IncludeTestDirsInBuild
+#define IncludeTestDirsInBuild NO
+#endif
+
+/* Misc. misc. */
+
+#ifndef RemoveTargetByMoving
+#define RemoveTargetByMoving NO /* affects Jmake.rules */
+#endif
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/site.dist b/web/glasgow/lit2x-0.16/mkworld/site.dist
new file mode 100644
index 0000000000..94b8c9a109
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/site.dist
@@ -0,0 +1,147 @@
+/************************************************************************
+
+General site-specific configuration information:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is where _general_ facts about your local computing environment
+are recorded.
+
+_Project-specific_ facts go in "site-<project>.jm", and facts specific
+to a ``setup'' of a project (unlikely...) go in
+"site-<project>-<setup>.jm".
+
+As you will see, the general style for setting these configuration facts is:
+
+ #ifndef ABuildParameter
+ #define ABuildParameter myvalue
+ #endif
+
+This particular file is for the Computing Science Dept at Glasgow
+University.
+************************************************************************/
+
+#ifndef PerlCmd
+#if defined(LinuxOSPlatform)
+#define PerlCmd /usr/bin/perl
+#else
+#define PerlCmd /usr/local/bin/perl
+#endif /* ! Linux */
+#endif /* PerlCmd */
+
+/* For "make tags", we recommend "etags" from the Emacs distribution.
+ (we supply a variant in the GHC distribution; grasp-utils/etags)
+ If not readily available on your search PATH, say where to find it here.
+ */
+#ifndef CTagsCmd
+#define CTagsCmd $(ETAGS)
+#endif
+
+/*
+ * Site-specific compiler things: for Glasgow
+ */
+
+/* --------------- C compiler --------------------------------- */
+/* we have gcc [by which we mean version 2.n] for sun4s and sun3s;
+ IT IS GOOD TO SAY `YES' !
+ (It is *essential* for the Glasgow Haskell compiler)
+ */
+#ifndef HaveGcc
+#if defined(SparcArchitecture) \
+ || defined(m68kArchitecture) \
+ || defined(AlphaArchitecture) \
+ || defined(LinuxOSPlatform)
+#define HaveGcc YES
+#else
+#define HaveGcc NO
+#endif /* ! one of those */
+#endif /* ! HaveGcc */
+
+#ifndef WhatGccIsCalled /* version 2.n, please */
+#if defined(m68kArchitecture)
+#define WhatGccIsCalled gcc-m68k /* to tell the truth, we cross-compile */
+#else
+#define WhatGccIsCalled gcc
+#endif /* m68k */
+#endif /* ! WhatGccIsCalled */
+
+/* Set UseGcc to YES if you want to use it for "ordinary" C compilations.
+ YES, by default. "UseGcc" *and* "HaveGcc" both have to be YES for
+ anything to happen.
+
+ This is *independent* of whether you set "UseGccForNormalGhcAsm"
+ and/or "UseGccForOptGhcAsm", which are GHC-specific.
+*/
+
+#if ! defined(UseGcc) && HaveGcc == YES
+#define UseGcc YES
+#endif /* ! UseGcc */
+
+/* --------------- "standard" Haskell compiler --------------------------- */
+
+/* What do we *have*?
+ We have Chalmers "hbc" for sun4s
+ We have Glasgow Haskell (called "glhc" at Glasgow) for sun4s and sun3s
+*/
+#ifndef HaveChalmersHBC
+#if defined(SparcArchitecture) \
+ || defined(LinuxOSPlatform)
+#define HaveChalmersHBC YES
+#else
+#define HaveChalmersHBC NO
+#endif /* ! one of those */
+#endif /* ! HaveChalmersHBC */
+
+#ifndef HaveGlasgowHaskell
+#if defined(m68kArchitecture) \
+ || defined(SparcArchitecture) \
+ || defined(AlphaArchitecture)
+#define HaveGlasgowHaskell YES
+#else
+#define HaveGlasgowHaskell NO
+#endif /* ! m68k or sparc */
+#endif /* ! HaveGlasgowHaskell */
+
+#ifndef WhatGhcIsCalled /* Glasgow Haskell compiler */
+#define WhatGhcIsCalled ghc
+#endif
+
+/* What do we *use* for our "standard Haskell compiler"?
+ A "setup" may very well set this (mkworld/site-<project>-<setup>.jm);
+ the default is Glasgow Haskell.
+*/
+#if !defined(UseGlasgowHaskell) && !defined(UseChalmersHBC)
+#define UseGlasgowHaskell YES
+#endif
+
+/* Finally: set "HaskellCompileCmd" (your "standard Haskell compiler")
+*/
+#ifndef HaskellCompileCmd
+#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
+#define HaskellCompileCmd WhatGhcIsCalled
+#else /* ! ...GlasgowHaskell */
+#if HaveChalmersHBC == YES && UseChalmersHBC == YES
+#define HaskellCompileCmd hbc
+#else
+#define HaskellCompileCmd no_default_haskell_compiler_defined
+#endif /* ! ...ChalmersHBC */
+#endif /* ! ...GlasgowHaskell */
+#endif /* ! HaskellCompileCmd */
+
+/* --------------- V misc stuff --------------------------- */
+
+/* Your main directory for GNU Info files should come first.
+ If in doubt, get an Emacs person to do "C-h v Info-directory"
+ to tell you where Emacs looks for Info files.
+*/
+#ifndef DefaultInfoPath
+#if defined(LinuxOSPlatform)
+#define DefaultInfoPath /usr/emacs/info:.
+#else
+#define DefaultInfoPath /local/doc/info:.
+#endif
+#endif
+
+/* ugly, ain't it ? */
+#ifndef TgrindHelperCmd
+#define TgrindHelperCmd /usr/local/tex/lib/tgrind/HostPlatform/tfontedpr
+#endif
diff --git a/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.jm b/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.jm
new file mode 100644
index 0000000000..8a399a7ac5
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.jm
@@ -0,0 +1,154 @@
+# line 31 "suffixes-GEN.ljm"
+#ifndef LitSuffixRule
+#define LitSuffixRule(beforesuff,aftersuff) @@\
+CAT2(beforesuff,aftersuff): @@\
+ $(RM) $@ @@\
+ $(LIT2PGM) $(LIT2PGMFLAGS) -o $@ $< @@\
+ @chmod 444 $@ @@\
+ @@\
+beforesuff.itxi: @@\
+ $(RM) $@ @@\
+ $(LIT2TEXI) -c $(LIT2TEXIFLAGS) -o $@ $< @@\
+ @chmod 444 $@ @@\
+ @@\
+beforesuff.itex: @@\
+ $(RM) $@ @@\
+ $(LIT2LATEX) -c $(LIT2LATEXFLAGS) -o $@ $< @@\
+ @chmod 444 $@
+#endif /* LitSuffixRule */
+# line 59 "suffixes-GEN.ljm"
+#ifndef NormalLibraryObjectRule
+#define NormalLibraryObjectRule() @@\
+.c.o: @@\
+ RemoveTarget ($@) @@\
+ $(CC) -c $(CFLAGS) $*.c
+#endif
+# line 84 "suffixes-GEN.ljm"
+#ifndef HaskellSuffixRules
+#define HaskellSuffixRules() @@\
+SuffixRule_o_hi() @@\
+SuffixRule_lhs_o() @@\
+SuffixRule_hs_o()
+#endif /* !HaskellSuffixRules */
+# line 97 "suffixes-GEN.ljm"
+#ifndef SuffixRule_o_hi
+#define SuffixRule_o_hi() @@\
+.o.hi: @@\
+ @if [ ! -f $@ ] ; then \ @@\
+ echo $(RM) $< ; \ @@\
+ $(RM) $< ; \ @@\
+ set +e ; \ @@\
+ echo $(MAKE) HC="$(HC)" HCFLAGS="$(HCFLAGS)" $(MFLAGS) $< ; \ @@\
+ $(MAKE) HC="$(HC)" HCFLAGS="$(HCFLAGS)" $(MFLAGS) $< ; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ fi
+#endif /* !SuffixRule_o_hi */
+# line 114 "suffixes-GEN.ljm"
+#ifndef SuffixRule_hs_o
+#define SuffixRule_hs_o() @@\
+.hs.o: \
+_body_HaskellCompileWithSpecifiedFlags($<,$*,hs,-c $(HCFLAGS))
+#endif /* !SuffixRule_hs_o */
+
+#ifndef SuffixRule_lhs_o
+#define SuffixRule_lhs_o() @@\
+.lhs.o: \
+_body_HaskellCompileWithSpecifiedFlags($<,$*,lhs,-c $(HCFLAGS))
+#endif /* !SuffixRule_lhs_o */
+# line 136 "suffixes-GEN.ljm"
+#ifndef DocProcessingSuffixRules
+#define DocProcessingSuffixRules() @@\
+.tex.dvi: @@\
+ $(RM) $@ @@\
+ $(LTX) $< @@\
+ @@\
+.verb.tex: @@\
+ $(RM) $*.tex @@\
+ expand $*.verb | $(VERBATIM) > $*.tex @@\
+ @@\
+.tib.tex: @@\
+ $(RM) $*.tex $*.verb-t.tex @@\
+ $(TIB) $*.tib @@\
+ expand $*.tib-t.tex | $(VERBATIM) > $*.tex @@\
+ $(RM) $*.tib-t.tex @@\
+ @@\
+.fig.ps: @@\
+ $(RM) $@ @@\
+ fig2dev -L ps $< $@ @@\
+ @@\
+.fig.tex: @@\
+ $(RM) $@ @@\
+ fig2dev -L latex $< $@
+
+#endif /* ! DocProcessingSuffixRules */
+# line 170 "suffixes-GEN.ljm"
+.SUFFIXES: .xdvi .ps .dvi .tex .fig .tib .verb .itex .itxi .lit \
+ _p.o .o .s .hi .hc .lhc .lhs .hs \
+ .prl .lprl \
+ .sh .lsh \
+ .c .lc .h .lh .lex .llex .y \
+ .ljm .jm
+# line 185 "suffixes-GEN.ljm"
+.s.o:
+ $(RM) $@
+ $(AS) $(ASFLAGS) -o $@ $< || $(RM) $@
+# line 200 "suffixes-GEN.ljm"
+LitSuffixRule(.ljm,.jm) /* mkworld */
+
+#if SuffixRules_WantLiterate == YES
+
+LitSuffixRule(.lit,/*none*/) /* no language really */
+LitSuffixRule(.lhs,.hs) /* Haskell */
+LitSuffixRule(.lhc,.hc) /* Haskell assembler (C) */
+LitSuffixRule(.lprl,.prl) /* Perl */
+LitSuffixRule(.lsh,.sh) /* Bourne shell */
+LitSuffixRule(.lc,.c) /* C */
+LitSuffixRule(.lh,.h)
+LitSuffixRule(.llex,.lex) /* Lex */
+
+/* extra rule... flex can't handle #line's yet */
+/* also: save the .lex file in case of some debugging need */
+.llex.c:
+ $(RM) $@ $*.lex $*.lex.save
+ $(LIT2PGM) $(LIT2PGMFLAGS) $< > $*.lex
+ $(FLEX) $*.lex && mv $*.lex $*.lex.save && mv lex.yy.c $*.c
+
+#endif /* SuffixRules_WantLiterate */
+# line 234 "suffixes-GEN.ljm"
+.y.c:
+ @echo please use an explicit "YaccRunWithExpectMsg" macro
+
+.lex.c: /* ToDo: should make it do flex */
+ $(RM) $@
+ $(LEX) -t $(LFLAGS) $< > $@ || ( $(RM) $@ && exit 1 )
+# line 244 "suffixes-GEN.ljm"
+#if CCompilerGroksMinusCMinusO == YES
+.c.o:
+ $(RM) $@
+ $(CC) $(CFLAGS) -c $< -o $@
+.c.s:
+ $(RM) $@
+ $(CC) $(CFLAGS) -S $< -o $@
+
+#else /* ! CCompilerGroksMinusCMinusO */
+.c.o:
+ $(RM) $@
+ $(CC) $(CFLAGS) -c $<
+ @if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \
+ echo mv $(@F) $@ ; \
+ mv $(@F) $@ ; \
+ fi
+.c.s:
+ $(RM) $@
+ $(CC) $(CFLAGS) -S $<
+ @if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \
+ echo mv $(@F) $@ ; \
+ mv $(@F) $@ ; \
+ fi
+#endif /* ! CCompilerGroksMinusCMinusO */
+# line 287 "suffixes-GEN.ljm"
+#if SuffixRules_WantDocProcessing == YES
+DocProcessingSuffixRules()
+#endif /* SuffixRules_WantDocProcessing */
diff --git a/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.ljm b/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.ljm
new file mode 100644
index 0000000000..ad1fe6d2b7
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/suffixes-GEN.ljm
@@ -0,0 +1,290 @@
+%************************************************************************
+%* *
+\section[mkworld-suffix-rules]{Default stuff for suffix rules}
+%* *
+%************************************************************************
+
+We are keen on suffix rules, rather than pattern rules, because not
+all makes do the latter. Sigh.
+
+Suffix rules come in three blobs: (1)~the unavoidable ones [few];
+(2)~the ``always for this project'' ones [turn-off-able]; and (3)~the
+per-Jmakefile ones (you must ``ask for'' these in each Jmakefile where
+you need them.
+
+%************************************************************************
+%* *
+\subsection[mkworld-suffix-macros]{Macros for making up suffix rules}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffix-macros-literate]{Suffix-rule macros for literate stuff}
+%* *
+%************************************************************************
+
+The following rule generator assumes the @beforesuff->aftersuff@ is
+known to the literate programming system.
+
+\begin{code}
+#ifndef LitSuffixRule
+#define LitSuffixRule(beforesuff,aftersuff) @@\
+CAT2(beforesuff,aftersuff): @@\
+ $(RM) $@ @@\
+ $(LIT2PGM) $(LIT2PGMFLAGS) -o $@ $< @@\
+ @chmod 444 $@ @@\
+ @@\
+beforesuff.itxi: @@\
+ $(RM) $@ @@\
+ $(LIT2TEXI) -c $(LIT2TEXIFLAGS) -o $@ $< @@\
+ @chmod 444 $@ @@\
+ @@\
+beforesuff.itex: @@\
+ $(RM) $@ @@\
+ $(LIT2LATEX) -c $(LIT2LATEXFLAGS) -o $@ $< @@\
+ @chmod 444 $@
+#endif /* LitSuffixRule */
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffix-macros-C]{Suffix-rule macros for C}
+%* *
+%************************************************************************
+
+For objects in libraries: these rules are invoked when you want to
+override some default suffix rules.
+\begin{code}
+#ifndef NormalLibraryObjectRule
+#define NormalLibraryObjectRule() @@\
+.c.o: @@\
+ RemoveTarget ($@) @@\
+ $(CC) -c $(CFLAGS) $*.c
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffix-macros-Haskell]{Suffix-rule macros for Haskell}
+%* *
+%************************************************************************
+
+There are several varying flavours of Haskell-related suffix rules;
+each such ``set'' of suffix rules should include...:
+
+\begin{verbatim}
+.o -> .hi # hacky pseudo-dependency to mk .hi file if non-existent
+.lhs -> .o
+.hs -> .o
+\end{verbatim}
+
+This is the {\em default}; a project or setup could override it.
+\begin{code}
+#ifndef HaskellSuffixRules
+#define HaskellSuffixRules() @@\
+SuffixRule_o_hi() @@\
+SuffixRule_lhs_o() @@\
+SuffixRule_hs_o()
+#endif /* !HaskellSuffixRules */
+\end{code}
+
+We use the internal mkworld CPP macro
+@_body_HaskellCompileWithSpecifiedFlags@, which is shared w/ other
+mkworld stuff. This keeps the magic to exactly one place.
+
+\begin{code}
+#ifndef SuffixRule_o_hi
+#define SuffixRule_o_hi() @@\
+.o.hi: @@\
+ @if [ ! -f $@ ] ; then \ @@\
+ echo $(RM) $< ; \ @@\
+ $(RM) $< ; \ @@\
+ set +e ; \ @@\
+ echo $(MAKE) HC="$(HC)" HCFLAGS="$(HCFLAGS)" $(MFLAGS) $< ; \ @@\
+ $(MAKE) HC="$(HC)" HCFLAGS="$(HCFLAGS)" $(MFLAGS) $< ; \ @@\
+ if [ $$? -ne 0 ] ; then \ @@\
+ exit 1; \ @@\
+ fi ; \ @@\
+ fi
+#endif /* !SuffixRule_o_hi */
+\end{code}
+
+\begin{code}
+#ifndef SuffixRule_hs_o
+#define SuffixRule_hs_o() @@\
+.hs.o: \
+_body_HaskellCompileWithSpecifiedFlags($<,$*,hs,-c $(HCFLAGS))
+#endif /* !SuffixRule_hs_o */
+
+#ifndef SuffixRule_lhs_o
+#define SuffixRule_lhs_o() @@\
+.lhs.o: \
+_body_HaskellCompileWithSpecifiedFlags($<,$*,lhs,-c $(HCFLAGS))
+#endif /* !SuffixRule_lhs_o */
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffix-macros-doc]{Suffix-rule macros for document processing}
+%* *
+%************************************************************************
+
+You have to ask for these.
+
+\begin{code}
+#ifndef DocProcessingSuffixRules
+#define DocProcessingSuffixRules() @@\
+.tex.dvi: @@\
+ $(RM) $@ @@\
+ $(LTX) $< @@\
+ @@\
+.verb.tex: @@\
+ $(RM) $*.tex @@\
+ expand $*.verb | $(VERBATIM) > $*.tex @@\
+ @@\
+.tib.tex: @@\
+ $(RM) $*.tex $*.verb-t.tex @@\
+ $(TIB) $*.tib @@\
+ expand $*.tib-t.tex | $(VERBATIM) > $*.tex @@\
+ $(RM) $*.tib-t.tex @@\
+ @@\
+.fig.ps: @@\
+ $(RM) $@ @@\
+ fig2dev -L ps $< $@ @@\
+ @@\
+.fig.tex: @@\
+ $(RM) $@ @@\
+ fig2dev -L latex $< $@
+
+#endif /* ! DocProcessingSuffixRules */
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-suffix-rule-text]{Generate actual suffix-rule text}
+%* *
+%************************************************************************
+
+\begin{code}
+.SUFFIXES: .xdvi .ps .dvi .tex .fig .tib .verb .itex .itxi .lit \
+ _p.o .o .s .hi .hc .lhc .lhs .hs \
+ .prl .lprl \
+ .sh .lsh \
+ .c .lc .h .lh .lex .llex .y \
+ .ljm .jm
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffixes-general]{Suffix rules---very general ones}
+%* *
+%************************************************************************
+
+\begin{code}
+.s.o:
+ $(RM) $@
+ $(AS) $(ASFLAGS) -o $@ $< || $(RM) $@
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffixes-literate]{Suffix rules for literate programming}
+%* *
+%************************************************************************
+
+The \tr{.ljm->.jm} rule isn't optional, because the mkworld system
+uses it.
+
+\begin{code}
+LitSuffixRule(.ljm,.jm) /* mkworld */
+
+#if SuffixRules_WantLiterate == YES
+
+LitSuffixRule(.lit,/*none*/) /* no language really */
+LitSuffixRule(.lhs,.hs) /* Haskell */
+LitSuffixRule(.lhc,.hc) /* Haskell assembler (C) */
+LitSuffixRule(.lprl,.prl) /* Perl */
+LitSuffixRule(.lsh,.sh) /* Bourne shell */
+LitSuffixRule(.lc,.c) /* C */
+LitSuffixRule(.lh,.h)
+LitSuffixRule(.llex,.lex) /* Lex */
+
+/* extra rule... flex can't handle #line's yet */
+/* also: save the .lex file in case of some debugging need */
+.llex.c:
+ $(RM) $@ $*.lex $*.lex.save
+ $(LIT2PGM) $(LIT2PGMFLAGS) $< > $*.lex
+ $(FLEX) $*.lex && mv $*.lex $*.lex.save && mv lex.yy.c $*.c
+
+#endif /* SuffixRules_WantLiterate */
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffixes-C]{Suffix rules for C/lex/yacc programming}
+%* *
+%************************************************************************
+
+See also the ``literate lex'' (llex) rule in the literate section, above.
+
+We don't support the \tr{.y.c} suffix rule; an explicit
+@YaccRunWithExpectMsg@ is better.
+\begin{code}
+.y.c:
+ @echo please use an explicit "YaccRunWithExpectMsg" macro
+
+.lex.c: /* ToDo: should make it do flex */
+ $(RM) $@
+ $(LEX) -t $(LFLAGS) $< > $@ || ( $(RM) $@ && exit 1 )
+\end{code}
+
+NB: avoid \tr{-o <something>} because of braindead C compilers.
+\begin{code}
+#if CCompilerGroksMinusCMinusO == YES
+.c.o:
+ $(RM) $@
+ $(CC) $(CFLAGS) -c $< -o $@
+.c.s:
+ $(RM) $@
+ $(CC) $(CFLAGS) -S $< -o $@
+
+#else /* ! CCompilerGroksMinusCMinusO */
+.c.o:
+ $(RM) $@
+ $(CC) $(CFLAGS) -c $<
+ @if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \
+ echo mv $(@F) $@ ; \
+ mv $(@F) $@ ; \
+ fi
+.c.s:
+ $(RM) $@
+ $(CC) $(CFLAGS) -S $<
+ @if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \
+ echo mv $(@F) $@ ; \
+ mv $(@F) $@ ; \
+ fi
+#endif /* ! CCompilerGroksMinusCMinusO */
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffixes-haskell]{Suffix rules for Haskell programming}
+%* *
+%************************************************************************
+
+Suffix rules for Haskell are {\em not} put in by default. A Jmakefile
+must ask for one specifically, using one of the macros defined in
+macros section, above (\sectionref{mkworld-suffix-macros-Haskell}).
+
+%************************************************************************
+%* *
+\subsubsection[mkworld-suffixes-docs]{Suffix rules for document processing (LaTeX/tib/fig/etc)}
+%* *
+%************************************************************************
+
+\begin{code}
+#if SuffixRules_WantDocProcessing == YES
+DocProcessingSuffixRules()
+#endif /* SuffixRules_WantDocProcessing */
+\end{code}
diff --git a/web/glasgow/lit2x-0.16/mkworld/utils-GEN.jm b/web/glasgow/lit2x-0.16/mkworld/utils-GEN.jm
new file mode 100644
index 0000000000..46e2d3c97a
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/utils-GEN.jm
@@ -0,0 +1,1096 @@
+# line 25 "utils-GEN.ljm"
+#ifndef ArCmd
+#if HasSysVishArAndRanlib == YES
+#define ArCmd ar clqs
+#else
+#define ArCmd ar clq
+#endif
+#endif
+AR = ArCmd
+# line 36 "utils-GEN.ljm"
+#ifndef ArchCmd
+#define ArchCmd arch
+#endif
+ARCH_CMD = ArchCmd
+
+#ifndef MachCmd
+#define MachCmd mach
+#endif
+MACH_CMD = MachCmd
+
+#ifndef AsCmd
+#define AsCmd as
+#endif
+AS = AsCmd
+
+#ifndef WhatGccIsCalled /* version 2.n, please */
+#define WhatGccIsCalled gcc
+#endif
+
+#ifndef CcCmd
+#if (HaveGcc == YES) && (UseGcc == YES)
+#define CcCmd WhatGccIsCalled
+#else
+#define CcCmd cc
+#endif /* ! HaveGcc etc */
+#endif /* CcCmd */
+CC = CcCmd
+
+#ifndef CompressCmd
+#define CompressCmd compress
+#endif
+COMPRESS = CompressCmd
+
+#ifndef CpCmd
+#define CpCmd cp
+#endif
+CP = CpCmd
+
+#ifndef CppCmd
+#define CppCmd /lib/cpp
+#endif
+#ifndef PreProcessCmd
+#define PreProcessCmd CcCmd -E
+#endif
+CPP = CppCmd $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) /* simple filters */
+PREPROCESSCMD = PreProcessCmd $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) /* preferred; mdep */
+
+#ifndef InstallCmd
+#define InstallCmd install
+#endif /* InstallCmd */
+INSTALL = InstallCmd
+#ifndef InstallingByDefault
+#define InstallingByDefault 0
+#endif
+INSTALLING = InstallingByDefault
+
+#ifndef LexCmd
+#ifdef UseFlexForLexCmd
+#define LexCmd flex
+#else
+#define LexCmd lex
+#endif
+#endif
+#ifndef FlexCmd
+#define FlexCmd flex -s
+#endif
+LEX = LexCmd
+FLEX = FlexCmd $(EXTRA_FLEX_FLAGS) /* this is asking for it... */
+
+/* the installed Haskell compiler */
+#ifndef HaskellCompileCmd
+#define HaskellCompileCmd hc
+#endif
+HC = HaskellCompileCmd
+
+#ifndef LaTeXCmd
+#define LaTeXCmd latex
+#endif
+LATEX = LaTeXCmd
+/* see also the LaTeX-wrapper script, LTX, in AllProjects */
+
+#ifndef LdCmd
+#define LdCmd ld
+#endif
+LD = LdCmd
+
+#ifndef LintCmd
+#define LintCmd lint
+#endif
+LINT = LintCmd
+
+#ifndef LnCmd
+#define LnCmd ln -s
+#endif /* LnCmd */
+LN = LnCmd
+
+#ifndef MakeCmd
+#define MakeCmd make
+#endif
+/* this might be useful at some point ... */
+#ifndef MakeCmdIsGnuMake
+#define MakeCmdIsGnuMake NO
+#endif
+MAKE = MakeCmd
+
+#ifndef MvCmd
+#define MvCmd mv
+#endif
+MV = MvCmd
+
+#ifndef NroffCmd
+#define NroffCmd nroff
+#endif
+#ifndef ManMacros
+#define ManMacros -man
+#endif
+#ifndef MsMacros
+#define MsMacros -ms
+#endif
+NROFF = NroffCmd
+MANMACROS = ManMacros
+MSMACROS = MsMacros
+
+#ifndef PerlCmd
+#define PerlCmd /usr/bin/perl
+#endif
+PERL = PerlCmd
+
+#ifndef PicCmd
+#define PicCmd pic
+#endif
+PIC = PicCmd
+
+#ifndef PrinterCmd
+#define PrinterCmd lpr
+#endif
+PRINTER = PrinterCmd
+
+#ifndef RanlibCmd
+#if HasSysVishArAndRanlib == YES
+#define RanlibCmd /bin/true /* does nothing */
+#else
+#define RanlibCmd ranlib
+#endif
+#endif
+RANLIB = RanlibCmd
+
+#ifndef RmCmd
+#define RmCmd rm -f
+#endif
+RM = RmCmd
+/* a project may want to override CLEAN_CMD */
+
+/* see the comment about not having #*, under CleanTarget rule in Jmake.rules */
+/* ToDo: what about bbl files? */
+#ifndef FilesToClean
+#define FilesToClean *.CKP *.ln *.BAK *.bak *.o core a.out errs ,* *.a .emacs_* tags TAGS \
+ *.ind *.ilg *.idx *.idx-prev *.aux *.aux-prev *.dvi *.log *.toc *.lot *.lof \
+ *.blg *.info *.itxi *.itex *.cb
+#endif
+/* you can override this in various ways... */
+/* Real Men (TM) will have the following in their veryclean stuff:
+ Makefile
+ .??*~ *~ (emacs backup files)
+ *.tex *.texi
+ *.lex.c *.yacc.c [however this should be done...]
+ *.orig *.rej (patch droppings)
+*/
+#ifndef ExtraFilesToBeVeryClean
+#define ExtraFilesToBeVeryClean .??*~ *~ *.orig *.rej
+#endif
+CLEAN_CMD = $(RM) FilesToClean
+STD_VERY_CLEAN = ExtraFilesToBeVeryClean
+
+#ifndef SoelimCmd
+#ifndef UseSoelim
+#define SoelimCmd cat /* fake it */
+#else
+#if defined(UseInstalledUtils)
+#define SoelimCmd soelim
+#else
+#define SoelimCmd $(SOELIMSRC)/soelim
+#endif /* UseInstalledUtils */
+#endif /* UseSoelim */
+#endif /* SoelimCmd */
+SOELIM = SoelimCmd
+
+#ifndef CTagsCmd
+#define CTagsCmd $(ETAGS)
+#endif
+CTAGS = CTagsCmd
+
+#ifndef StripCmd
+#define StripCmd strip
+#endif
+STRIP = StripCmd
+
+#ifndef TblCmd
+#define TblCmd tbl
+#endif
+TBL = TblCmd
+
+#ifndef TeXCmd
+#define TeXCmd tex
+#endif
+TEX = TeXCmd
+
+#ifndef TgrindCmd
+#define TgrindCmd tgrind
+#endif
+/* the program that really does the tgrind'ing */
+#ifndef TgrindHelperCmd
+#define TgrindHelperCmd /usr/local/lib/tgrind/tfontedpr
+#endif
+TGRIND = TgrindCmd
+TGRIND_HELPER = TgrindHelperCmd
+
+#ifndef TibCmd
+#define TibCmd tib /* you could define this to "cat" if you don't have "tib"... */
+#endif /* (I didn't say it would be pretty...) */
+TIB = TibCmd
+
+#ifndef TimeCmd
+#define TimeCmd time
+#endif
+TIME = TimeCmd
+
+#ifndef TroffCmd
+#define TroffCmd troff
+#endif
+TROFF = TroffCmd
+
+#ifndef YaccCmd
+#define YaccCmd yacc
+#endif
+YACC = YaccCmd
+
+/* Note on the <pgm>NeededHere rules: they don't really check that
+ * the program elsewhere in the sources is really up-to-date;
+ * they really just arrange to go build it if it doesn't exist at all.
+ * This is usually good enough.
+ */
+
+/* general idea behind these things (__* is an internal macro) ... */
+
+#ifndef __SomeUtilNeededHere
+#if defined(UseInstalledUtils)
+#define __SomeUtilNeededHere(target,neededthing,neededthingsrcdir,neededthingmaketarg) /**/
+#else
+#define __SomeUtilNeededHere(target,neededthing,neededthingsrcdir,neededthingmaketarg) @@\
+ @@\
+target:: neededthing @@\
+ @@\
+neededthing: @@\
+ @echo "checking $@ over in" neededthingsrcdir "first..."; \ @@\
+ cd neededthingsrcdir; $(MAKE) neededthingmaketarg; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)"
+#endif /* ! UseInstalledUtils */
+#endif /* __SomeUtilNeededHere */
+
+/*# ------------------------------------------------ */
+/*# OTHER GENERALLY-USEFUL UTILS (w/ source provided) */
+
+#ifndef UseInstalledUtils
+UTILSRC = $(TOP)/grasp-utils
+SCRIPTSRC = $(UTILSRC)/scripts
+#endif
+
+/*# Configuration stuff (jmake, its friends and templates) */
+
+#ifndef JmkmfCmd
+#if defined(UseInstalledUtils)
+#define JmkmfCmd jmkmf
+#else
+#define JmkmfCmd jmkmf_used_only_with_installed_utils
+#endif
+#endif
+
+#ifndef JrestoredepsCmd
+#if defined(UseInstalledUtils)
+#define JrestoredepsCmd jrestoredeps
+#else
+#define JrestoredepsCmd $(JMAKESRC)/jrestoredeps
+#endif
+#endif
+
+#ifndef JmakeCmd
+#if defined(UseInstalledUtils)
+#define JmakeCmd jmake
+#else
+#define JmakeCmd $(JMAKESRC)/jmake
+#endif
+#endif
+/*
+ * JmakeNeededHere -- generate rules to compile jmake if its source is
+ * within this project's source tree.
+ *
+ * [doesn't quite fit std pattern in __SomeUtilNeededHere]
+ */
+#ifndef JmakeNeededHere
+#if defined(UseInstalledUtils)
+#define JmakeNeededHere(target) /**/
+#else
+#define JmakeNeededHere(target) @@\
+target:: $(JMAKE) @@\
+ @@\
+$(JMAKE): @@\
+ @(cd $(JMAKESRC); if [ -f Makefile ]; then \ @@\
+ echo "checking $@ in $(JMAKESRC) first..."; $(MAKE) all; else \ @@\
+ echo "bootstrapping $@ from Makefile.BOOT in $(JMAKESRC) first..."; \ @@\
+ $(MAKE) -f Makefile.BOOT BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)")
+#endif /* ! UseInstalledUtils */
+#endif /* JmakeNeededHere */
+
+JMKMF = JmkmfCmd
+JRESTOREDEPS = JrestoredepsCmd
+JMAKE = JmakeCmd
+
+/* the project config dir is assumed to be relative to $(TOP) */
+
+#if defined(UseInstalledUtils)
+#if defined(HaveProjectMkworldDir)
+JMAKE_CMD = $(JMKMF) -P $(PROJECTLABEL) -S $(SETUPLABEL) -C $(PROJ_MKWORLD_DIR) - $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#else
+JMAKE_CMD = $(JMKMF) -P $(PROJECTLABEL) -S $(SETUPLABEL) - $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#endif /* !HaveProjectMkworldDir */
+
+#else /* ! using installed jmake */
+JMAKESRC = $(TOP)/mkworld
+
+#if ProjectIsNone == YES
+#define ProjectJmFiles /*nothing*/
+#define SetupJmFiles /*nothing*/
+#else /* have a project... */
+#define ProjectJmFiles \
+ $(PROJ_MKWORLD_DIR)/site-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/only4-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/suffixes-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/macros-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/utils-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/install-$(PROJECTLABEL).jm
+
+#if SetupIsStd == YES
+#define SetupJmFiles /*nothing*/
+#else /* have project & a setup... */
+#define SetupJmFiles \
+ $(PROJ_MKWORLD_DIR)/site-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/only4-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/suffixes-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/macros-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/utils-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/install-$(PROJECTLABEL)-$(SETUPLABEL).jm
+#endif
+#endif
+MYJCONFIGFILES = $(JMAKESRC)/TEMPLATE.jm \
+ $(JMAKESRC)/plat-TRIGGERS.jm \
+ $(JMAKESRC)/PlatformFile \
+ $(JMAKESRC)/plat-DEF.jm \
+ $(JMAKESRC)/site.jm \
+ $(JMAKESRC)/site-DEF.jm \
+ $(JMAKESRC)/suffixes-GEN.jm \
+ $(JMAKESRC)/macros-GEN.jm \
+ $(JMAKESRC)/utils-GEN.jm \
+ $(JMAKESRC)/install-GEN.jm ProjectJmFiles SetupJmFiles
+
+#if defined(HaveProjectMkworldDir)
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -P $(PROJECTLABEL) -S $(SETUPLABEL) -C $(NEWTOP)$(PROJ_MKWORLD_DIR) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#else
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -P $(PROJECTLABEL) -S $(SETUPLABEL) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#endif /* ! HaveProjectMkworldDir */
+#endif /* ! using installed jmake */
+
+
+/*# GNU info system [hacked] */
+
+#ifndef InfoCmd
+#if defined(UseInstalledUtils)
+#define InfoCmd info
+#else
+#define InfoCmd $(INFOSRC)/info
+#endif
+#endif
+#ifndef MakeinfoCmd
+#if defined(UseInstalledUtils)
+#define MakeinfoCmd makeinfo
+#else
+#define MakeinfoCmd $(INFOSRC)/makeinfo
+#endif
+#endif
+#ifndef PostMakeinfoCmd
+#if defined(UseInstalledUtils)
+#define PostMakeinfoCmd postmakeinfo
+#else
+#define PostMakeinfoCmd $(INFOSRC)/postmakeinfo
+#endif
+#endif
+#ifndef InfoStuffNeededHere
+#if defined(UseInstalledUtils)
+#define InfoStuffNeededHere(target) /**/
+#else
+#define InfoStuffNeededHere(target) \
+__SomeUtilNeededHere(target,$(INFO) $(MAKEINFO) $(POSTMAKEINFO),$(INFOSRC),all)
+#endif /* ! UseInstalledUtils */
+#endif /* InfoStuffNeededHere */
+INFO = InfoCmd /* who _knows_ where these might be ... */
+MAKEINFO = MakeinfoCmd
+POSTMAKEINFO = PostMakeinfoCmd
+#ifndef UseInstalledUtils
+INFOSRC = $(LITSRC)/info-utils
+#endif
+
+/*# literate programming system */
+#ifndef Lit2PgmCmd
+#if defined(UseInstalledUtils)
+#define Lit2PgmCmd lit2pgm
+#else
+#define Lit2PgmCmd $(LITSRC)/lit2pgm
+#endif
+#endif
+#ifndef Lit2TexiCmd
+#if defined(UseInstalledUtils)
+#define Lit2TexiCmd lit2texi
+#else
+#define Lit2TexiCmd $(LITSRC)/lit2texi
+#endif
+#endif
+#ifndef Lit2LaTeXCmd
+#if defined(UseInstalledUtils)
+#define Lit2LaTeXCmd lit2latex
+#else
+#define Lit2LaTeXCmd $(LITSRC)/lit2latex
+#endif
+#endif
+#ifndef MkDependLitCmd
+#if defined(UseInstalledUtils)
+#define MkDependLitCmd mkdependlit
+#else
+#define MkDependLitCmd $(LITSRC)/mkdependlit
+#endif
+#endif
+#ifndef Lit2ChangeLogCmd
+#if defined(UseInstalledUtils)
+#define Lit2ChangeLogCmd lit2changelog
+#else
+#define Lit2ChangeLogCmd $(LITSRC)/lit2changelog
+#endif
+#endif
+
+/* NB: this *NeededHere rule offers LIMITED guarantee that
+ the literate-programming stuff is up-to-date when used
+*/
+#ifndef LitStuffNeededHere
+#if defined(UseInstalledUtils)
+#define LitStuffNeededHere(target) /**/
+#else
+#define LitStuffNeededHere(target) \
+ @@\
+target:: $(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex $(LITSRC)/mkdependlit $(LITSRC)/lit2changelog $(LITSRC)/lit-deatify @@\
+ @@\
+$(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex $(LITSRC)/mkdependlit $(LITSRC)/lit2changelog $(LITSRC)/lit-deatify: @@\
+ @(cd $(LITSRC); if [ -f lit2pgm ]; then \ @@\
+ echo "checking $@ in $(LITSRC) first..."; $(MAKE) all; else \ @@\
+ echo "bootstrapping $@ with ./lit2pgm.BOOT in $(LITSRC) first..."; \ @@\
+ $(MAKE) LIT2PGM="./lit2pgm.BOOT -Alit2pgm" lit-deatify all; fi; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)")
+#endif /* ! UseInstalledUtils */
+#endif /* LitStuffNeededHere */
+
+LIT2PGM = Lit2PgmCmd
+/* sometimes, we _must_ use the installed version of lit2pgm,
+ * e.g., for building lit2pgm itself
+ */
+LIT2TEXI = Lit2TexiCmd
+LIT2LATEX = Lit2LaTeXCmd
+MKDEPENDLIT = MkDependLitCmd
+LIT2CHANGELOG = Lit2ChangeLogCmd
+#ifndef UseInstalledUtils
+LITSRC = $(TOP)/literate
+#endif
+
+/*# mkdepend scripts for various languages */
+/*# ["mkdependlit" is under literate programming stuff above] */
+
+/* for these MkDepend things, we use the scripts only [for now] */
+
+#ifndef MkDependCSrc
+#define MkDependCSrc $(SCRIPTSRC)
+#endif
+#ifndef MkDependCCmd
+#if defined(UseInstalledUtils)
+#define MkDependCCmd mkdependC
+#else
+#define MkDependCCmd $(MKDEPENDCSRC)/mkdependC
+#endif /* ! installed */
+#endif /* MkDependCCmd */
+
+/*
+ MkdependCNeededHere -- generate rules to build the mkdependC program
+ if its source is within this project's source tree.
+
+ [kind of a weird one, for now at least]
+*/
+#ifndef MkDependCNeededHere
+#if defined(UseInstalledUtils)
+#define MkDependCNeededHere(target) /**/
+#else
+#define MkDependCNeededHere(target) \
+__SomeUtilNeededHere(target,$(MKDEPENDC),$(MKDEPENDCSRC),mkdependC)
+#endif /* UseInstalledUtils */
+#endif /* MkDependCNeededHere */
+MKDEPENDC = MkDependCCmd
+#ifndef UseInstalledUtils
+MKDEPENDCSRC = MkDependCSrc
+#endif
+
+#ifndef MkDependHSCmd /* this is the default; hope you have it! */
+#define MkDependHSCmd mkdependHS
+#endif
+#ifndef MkDependHSNeededHere /* ditto */
+#define MkDependHSNeededHere(targets) /*no such thing*/
+#endif
+MKDEPENDHS = MkDependHSCmd
+
+/* mkdependlit is with the literate stuff above */
+
+/* tags utilities */
+
+#ifndef PerlTagsSrc
+#define PerlTagsSrc $(SCRIPTSRC)
+#endif
+#if defined(UseInstalledUtils)
+#define PerlTagsCmd perltags
+#else
+#define PerlTagsCmd $(PERLTAGSSRC)/perltags
+#endif
+
+#ifndef PerlTagsNeededHere
+#if defined(UseInstalledUtils)
+#define PerlTagsNeededHere(target) /**/
+#else
+#define PerlTagsNeededHere(target) \
+__SomeUtilNeededHere(target,$(PERLTAGS),$(PERLTAGSSRC),perltags)
+#endif /* UseInstalledUtils */
+#endif /* PerlTagsNeededHere */
+PERLTAGS = PerlTagsCmd
+#ifndef UseInstalledUtils
+PERLTAGSSRC = PerlTagsSrc
+#endif
+
+/*# misc utilities */
+
+#ifndef FastmakeCmd
+#if defined(UseInstalledUtils)
+#define FastmakeCmd fastmake
+#else
+#define FastmakeCmd $(FASTMAKESRC)/fastmake
+#endif
+#endif
+#ifndef FastmakeNeededHere
+#if defined(UseInstalledUtils)
+#define FastmakeNeededHere(target) /**/
+#else
+#define FastmakeNeededHere(target) \
+__SomeUtilNeededHere(target,$(FASTMAKE),$(FASTMAKESRC),fastmake)
+#endif /* ! UseInstalledUtils */
+#endif /* FastmakeNeededHere */
+FASTMAKE = FastmakeCmd
+#ifndef UseInstalledUtils
+FASTMAKESRC = $(SCRIPTSRC)
+#endif
+
+#ifndef LtxCmd
+#if defined(UseInstalledUtils)
+#define LtxCmd ltx
+#else
+#define LtxCmd $(LTXSRC)/ltx
+#endif
+#endif
+#ifndef LtxNeededHere
+#if defined(UseInstalledUtils)
+#define LtxNeededHere(target) /**/
+#else
+#define LtxNeededHere(target) \
+__SomeUtilNeededHere(target,$(LTX),$(LTXSRC),ltx)
+#endif /* ! UseInstalledUtils */
+#endif /* LtxNeededHere */
+LTX = LtxCmd /* a LaTeX-wrapper script */
+#ifndef UseInstalledUtils
+LTXSRC = $(SCRIPTSRC)
+#endif
+
+#ifndef MkdirHierCmd
+#if defined(UseInstalledUtils)
+#define MkdirHierCmd mkdirhier
+#else
+#define MkdirHierCmd $(MKDIRHIERSRC)/mkdirhier
+#endif
+#endif
+#ifndef MkdirHierNeededHere
+#if defined(UseInstalledUtils)
+#define MkdirHierNeededHere(target) /**/
+#else
+#define MkdirHierNeededHere(target) \
+__SomeUtilNeededHere(target,$(MKDIRHIER),$(MKDIRHIERSRC),mkdirhier)
+#endif /* ! UseInstalledUtils */
+#endif /* MkdirHierNeededHere */
+MKDIRHIER = MkdirHierCmd
+#ifndef UseInstalledUtils
+MKDIRHIERSRC = $(SCRIPTSRC)
+#endif
+
+/* Simon Marlow says: Lndir is sometimes dubious; if you
+ have GNU cp, define "LndirCmd" to: cp -Rsv
+*/
+#ifndef LndirCmd
+#if defined(UseInstalledUtils)
+#define LndirCmd lndir
+#else
+#define LndirCmd $(LNDIRSRC)/lndir
+#endif
+#endif
+#ifndef LndirNeededHere
+#if defined(UseInstalledUtils)
+#define LndirNeededHere(target) /**/
+#else
+#define LndirNeededHere(target) \
+__SomeUtilNeededHere(target,$(LNDIR),$(LNDIRSRC),lndir)
+#endif /* ! UseInstalledUtils */
+#endif /* LndirNeededHere */
+LNDIR = LndirCmd
+#ifndef UseInstalledUtils
+LNDIRSRC = $(SCRIPTSRC)
+#endif
+
+#ifndef MsubCmd
+#if defined(UseInstalledUtils)
+#define MsubCmd msub
+#else
+#define MsubCmd $(MSUBSRC)/msub
+#endif /* ! installed */
+#endif /* MsubCmd */
+/* MsubNeededHere - generate rules to build the msub program
+ if its source is within this project's source tree. This rule
+ should be included manually once in each Jmakefile that generates
+ targets with msub. (Ideally it would be invoked automatically from
+ within each msub-target-generating rule, but then you have a million
+ sets of these rules in the Makefile. Ugh. This could be avoided if
+ there were some way for a rule to void itself after being invoked
+ once.)
+*/
+#ifndef MsubNeededHere
+#if defined(UseInstalledUtils)
+#define MsubNeededHere(target) /**/
+#else
+#define MsubNeededHere(target) \
+__SomeUtilNeededHere(target,$(MSUB),$(MSUBSRC),msub)
+#endif /* ! UseInstalledUtils */
+#endif /* MsubNeededHere */
+MSUB = MsubCmd
+#ifndef UseInstalledUtils
+MSUBSRC = $(UTILSRC)/msub
+#endif
+
+#ifndef EtagsCmd
+#if defined(UseInstalledUtils)
+#define EtagsCmd etags
+#else
+#define EtagsCmd $(ETAGSSRC)/etags
+#endif /* ! installed */
+#endif /* EtagsCmd */
+#ifndef EtagsNeededHere
+#if defined(UseInstalledUtils)
+#define EtagsNeededHere(target) /**/
+#else
+#define EtagsNeededHere(target) \
+__SomeUtilNeededHere(target,$(ETAGS),$(ETAGSSRC),etags)
+#endif /* ! UseInstalledUtils */
+#endif /* EtagsNeededHere */
+ETAGS = EtagsCmd
+#ifndef UseInstalledUtils
+ETAGSSRC = $(UTILSRC)/etags
+#endif
+
+#ifndef VerbatimCmd
+#if defined(UseInstalledUtils)
+#define VerbatimCmd verbatim
+#else
+#define VerbatimCmd $(VERBATIMSRC)/verbatim
+#endif /* ! installed */
+#endif /* VerbatimCmd */
+#ifndef VerbatimNeededHere
+#if defined(UseInstalledUtils)
+#define VerbatimNeededHere(target) /**/
+#else
+#define VerbatimNeededHere(target) \
+__SomeUtilNeededHere(target,$(VERBATIM),$(VERBATIMSRC),verbatim)
+#endif /* ! UseInstalledUtils */
+#endif /* VerbatimNeededHere */
+VERBATIM = VerbatimCmd
+#ifndef UseInstalledUtils
+VERBATIMSRC = $(UTILSRC)/verbatim
+#endif
+
+#ifndef RunStdTestCmd
+#if defined(UseInstalledUtils)
+#define RunStdTestCmd runstdtest
+#else
+#define RunStdTestCmd $(RUNSTDTESTSRC)/runstdtest
+#endif
+#endif
+#ifndef RunStdTestNeededHere
+#if defined(UseInstalledUtils)
+#define RunStdTestNeededHere(target) /**/
+#else
+#define RunStdTestNeededHere(target) \
+__SomeUtilNeededHere(target,$(RUNSTDTEST),$(RUNSTDTESTSRC),runstdtest)
+#endif /* ! UseInstalledUtils */
+#endif /* RunStdTestNeededHere */
+RUNSTDTEST = RunStdTestCmd
+#ifndef UseInstalledUtils
+RUNSTDTESTSRC = $(SCRIPTSRC)
+#endif
+# line 768 "utils-GEN.ljm"
+/* for the whole nasty business of flags for programs,
+ some naming conventions are worth remembering; for program <foo>:
+
+ <foo>FLAGS what is actually passed to <foo>; usually
+ built from pieces below
+
+ ALLPROJ_<foo>_<things> <things> needed for _all_ runs of <foo>;
+ probably set in one of the AllProject*
+ config files.
+ PLAT_<foo>_<things> <things> (options, defines, etc.) needed for
+ all runs of <foo> *on this platform*;
+ probably set in <platform>.cf.
+ PROJ_<foo>_<things> <things> needed for all runs of <foo>
+ related to this project; probably set in
+ one of the Project-* config files.
+ <foo>_<things> <things> needed for runs of <foo> in this
+ directory; set in its Jmakefile.
+ EXTRA_<foo>_<things> name reserved for adding <things> from the
+ command line.
+ GLUED_<foo>_<things> all the above, glued together; not for
+ human use.
+
+ <foo>_OPTS the usual name for options
+ <foo>_DEFINES CPP #defines
+ <foo>_INCLUDES CPP #includes
+ <foo>_IMPORTS Haskell "import"s
+
+ As a contrived example, the "makeinfo" program is usually called
+ with the $(MAKEINFOFLAGS), which would likely be put together as...
+
+ ALLPROJ_MAKEINFO_OPTS =
+ PLAT_MAKEINFO_OPTS =
+ PROJ_MAKEINFO_OPTS =
+ MAKEINFO_OPTS =
+ EXTRA_MAKEINFO_OPTS =
+ GLUED_MAKEINFO_OPTS =
+ MAKEINFOFLAGS = $(GLUED_MAKEINFO_OPTS)
+
+ and used as...
+
+ $(MAKEINFO) $(MAKEINFOFLAGS) ...
+
+ The related CPP names are as you would expect: e.g.,
+ ProjectMakeinfoOpts for PROJ_MAKEINFO_OPTS, ...
+
+ For systems of interacting programs (e.g., cpp, cc, lint, as, and ld),
+ things can be [considerably] messier.
+
+*/
+
+/* CPP definitions for CPP #includes; -I must be explicit */
+
+/* I have not separated use of CPP w/ CC vs standalone... */
+
+#ifndef AllProjectsCppIncludes
+#define AllProjectsCppIncludes /*none*/
+#endif
+#ifndef PlatformCppIncludes
+#define PlatformCppIncludes /*none*/
+#endif
+#ifndef ProjectCppIncludes
+#define ProjectCppIncludes /*none*/
+#endif
+#ifndef SetupCppIncludes
+#define SetupCppIncludes /*none*/
+#endif
+GenerateOptionsMakeVars(CPP,INCLUDES,AllProjectsCppIncludes,PlatformCppIncludes,ProjectCppIncludes,SetupCppIncludes)
+
+/* CPP definitions for #defines */
+
+#ifndef AllProjectsCppDefines
+#define AllProjectsCppDefines /*none*/
+#endif
+#ifndef PlatformCppDefines
+#define PlatformCppDefines /**/
+#endif /* PlatformCppDefines */
+#ifndef ProjectCppDefines
+#define ProjectCppDefines /*none*/
+#endif
+#ifndef SetupCppDefines
+#define SetupCppDefines /*none*/
+#endif
+GenerateOptionsMakeVars(CPP,DEFINES,AllProjectsCppDefines,PlatformCppDefines,ProjectCppDefines,SetupCppDefines)
+
+/*# C-compiler (and cpp ... and lint) options */
+
+#ifndef AllProjectsCcOpts
+#define AllProjectsCcOpts /*none*/
+#endif
+#ifndef PlatformCcOpts
+#define PlatformCcOpts /*none*/
+#endif
+#ifndef ProjectCcOpts
+#define ProjectCcOpts /*none*/
+#endif
+#ifndef SetupCcOpts
+#define SetupCcOpts /*none*/
+#endif
+GenerateOptionsMakeVars(CC,OPTS,AllProjectsCcOpts,PlatformCcOpts,ProjectCcOpts,SetupCcOpts)
+
+CFLAGS = $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) $(GLUED_CC_OPTS)
+
+/*# Haskell compiler (and cpp ... and lint) options */
+
+#ifndef AllProjectsHcOpts
+#define AllProjectsHcOpts /*none*/
+#endif
+#ifndef PlatformHcOpts
+#define PlatformHcOpts /*none*/
+#endif
+#ifndef ProjectHcOpts
+#define ProjectHcOpts /*none*/
+#endif
+#ifndef SetupHcOpts
+#define SetupHcOpts /*none*/
+#endif
+GenerateOptionsMakeVars(HC,OPTS,AllProjectsHcOpts,PlatformHcOpts,ProjectHcOpts,SetupHcOpts)
+
+#ifndef AllProjectsHcImports
+#define AllProjectsHcImports /*none*/
+#endif
+#ifndef PlatformHcImports
+#define PlatformHcImports /*none*/
+#endif
+#ifndef ProjectHcImports
+#define ProjectHcImports /*none*/
+#endif
+#ifndef SetupHcImports
+#define SetupHcImports /*none*/
+#endif
+GenerateOptionsMakeVars(HC,IMPORTS,AllProjectsHcImports,PlatformHcImports,ProjectHcImports,SetupHcImports)
+HCFLAGS = $(GLUED_HC_IMPORTS) $(GLUED_CPP_DEFINES) $(GLUED_HC_OPTS)
+
+/*# linker options */
+
+#ifndef AllProjectsLdOpts
+#define AllProjectsLdOpts /*none*//* -X -r "combine" flags (?) */
+#endif
+#ifndef PlatformLdOpts
+#define PlatformLdOpts /*none*/
+#endif
+#ifndef ProjectLdOpts
+#define ProjectLdOpts /*none*/
+#endif
+#ifndef SetupLdOpts
+#define SetupLdOpts /*none*/
+#endif
+#ifndef AllProjectsLdLibraries
+#define AllProjectsLdLibraries /*none*/
+#endif
+#ifndef PlatformLdLibraries
+#define PlatformLdLibraries /*none*/
+#endif
+#ifndef ProjectLdLibraries
+#define ProjectLdLibraries /*none*/
+#endif
+#ifndef SetupLdLibraries
+#define SetupLdLibraries /*none*/
+#endif
+GenerateOptionsMakeVars(LD,OPTS,AllProjectsLdOpts,PlatformLdOpts,ProjectLdOpts,SetupLdOpts)
+GenerateOptionsMakeVars(LD,LIBRARIES,AllProjectsLdLibraries,PlatformLdLibraries,ProjectLdLibraries,SetupLdLibraries)
+LDOPTIONS = $(GLUED_LD_OPTS) /* ToDo: and the libraries ? */
+
+/* lint stuff not tidied up yet */
+
+#ifndef LintLibFlag
+#define LintLibFlag -C
+#endif
+#ifndef LintOpts
+#define LintOpts -axz
+#endif
+LINTLIBFLAG = LintLibFlag
+LINTOPTS = LintOpts
+LINTFLAGS = $(LINTOPTS) -DLINT $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES)
+
+/*# literate-stuff options */
+
+/* some options are common (general) to all lit2* pgms; others specific */
+
+#ifndef AllProjectsGenLitOpts
+#define AllProjectsGenLitOpts /*none*/
+#endif
+#ifndef PlatformGenLitOpts
+#define PlatformGenLitOpts /*none*/
+#endif
+#ifndef ProjectGenLitOpts
+#define ProjectGenLitOpts /*none*/
+#endif
+#ifndef SetupGenLitOpts
+#define SetupGenLitOpts /*none*/
+#endif
+GenerateOptionsMakeVars(GENLIT,OPTS,AllProjectsGenLitOpts,PlatformGenLitOpts,ProjectGenLitOpts,SetupGenLitOpts)
+
+#ifndef AllProjectsLit2pgmOpts
+#define AllProjectsLit2pgmOpts /*none*/
+#endif
+#ifndef PlatformLit2pgmOpts
+#define PlatformLit2pgmOpts /*none*/
+#endif
+#ifndef ProjectLit2pgmOpts
+#define ProjectLit2pgmOpts /*none*/
+#endif
+#ifndef SetupLit2pgmOpts
+#define SetupLit2pgmOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2PGM,OPTS,AllProjectsLit2pgmOpts,PlatformLit2pgmOpts,ProjectLit2pgmOpts,SetupLit2pgmOpts)
+#ifndef AllProjectsLit2texiOpts
+#define AllProjectsLit2texiOpts /*none*/
+#endif
+#ifndef PlatformLit2texiOpts
+#define PlatformLit2texiOpts /*none*/
+#endif
+#ifndef ProjectLit2texiOpts
+#define ProjectLit2texiOpts /*none*/
+#endif
+#ifndef SetupLit2texiOpts
+#define SetupLit2texiOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2TEXI,OPTS,AllProjectsLit2texiOpts,PlatformLit2texiOpts,ProjectLit2texiOpts,SetupLit2texiOpts)
+#ifndef AllProjectsLit2latexOpts
+#define AllProjectsLit2latexOpts /*none*/
+#endif
+#ifndef PlatformLit2latexOpts
+#define PlatformLit2latexOpts /*none*/
+#endif
+#ifndef ProjectLit2latexOpts
+#define ProjectLit2latexOpts /*none*/
+#endif
+#ifndef SetupLit2latexOpts
+#define SetupLit2latexOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2LATEX,OPTS,AllProjectsLit2latexOpts,PlatformLit2latexOpts,ProjectLit2latexOpts,SetupLit2latexOpts)
+#ifndef AllProjectsLit2changelogOpts
+#define AllProjectsLit2changelogOpts /*none*/
+#endif
+#ifndef PlatformLit2changelogOpts
+#define PlatformLit2changelogOpts /*none*/
+#endif
+#ifndef ProjectLit2changelogOpts
+#define ProjectLit2changelogOpts /*none*/
+#endif
+#ifndef SetupLit2changelogOpts
+#define SetupLit2changelogOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2CHANGELOG,OPTS,AllProjectsLit2changelogOpts,PlatformLit2changelogOpts,ProjectLit2changelogOpts,SetupLit2changelogOpts)
+#ifndef AllProjectsMkDependLitOpts
+#define AllProjectsMkDependLitOpts /*none*/
+#endif
+#ifndef PlatformMkDependLitOpts
+#define PlatformMkDependLitOpts /*none*/
+#endif
+#ifndef ProjectMkDependLitOpts
+#define ProjectMkDependLitOpts /*none*/
+#endif
+#ifndef SetupMkDependLitOpts
+#define SetupMkDependLitOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDLIT,OPTS,AllProjectsMkDependLitOpts,PlatformMkDependLitOpts,ProjectMkDependLitOpts,SetupMkDependLitOpts)
+
+LIT2PGMFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2PGM_OPTS)
+LIT2TEXIFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2TEXI_OPTS)
+LIT2LATEXFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2LATEX_OPTS)
+LIT2CHANGELOGFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2CHANGELOG_OPTS)
+MKDEPENDLITFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_MKDEPENDLIT_OPTS)
+
+/* same for other MkDepend things */
+
+#ifndef AllProjectsMkDependCOpts
+#define AllProjectsMkDependCOpts /*none*/
+#endif
+#ifndef PlatformMkDependCOpts
+#define PlatformMkDependCOpts /*none*/
+#endif
+#ifndef ProjectMkDependCOpts
+#define ProjectMkDependCOpts /*none*/
+#endif
+#ifndef SetupMkDependCOpts
+#define SetupMkDependCOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDC,OPTS,AllProjectsMkDependCOpts,PlatformMkDependCOpts,ProjectMkDependCOpts,SetupMkDependCOpts)
+MKDEPENDCFLAGS = $(GLUED_MKDEPENDC_OPTS)
+
+#ifndef AllProjectsMkDependHSOpts
+#define AllProjectsMkDependHSOpts /*none*/
+#endif
+#ifndef PlatformMkDependHSOpts
+#define PlatformMkDependHSOpts /*none*/
+#endif
+#ifndef ProjectMkDependHSOpts
+#define ProjectMkDependHSOpts /*none*/
+#endif
+#ifndef SetupMkDependHSOpts
+#define SetupMkDependHSOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDHS,OPTS,AllProjectsMkDependHSOpts,PlatformMkDependHSOpts,ProjectMkDependHSOpts,SetupMkDependHSOpts)
+MKDEPENDHSFLAGS = $(GLUED_MKDEPENDHS_OPTS)
+
+/* same for tags stuff */
+
+#ifndef AllProjectsCTagsOpts
+#define AllProjectsCTagsOpts -e -w /* emacs-style; no warnings */
+#endif
+#ifndef PlatformCTagsOpts
+#define PlatformCTagsOpts /*none*/
+#endif
+#ifndef ProjectCTagsOpts
+#define ProjectCTagsOpts /*none*/
+#endif
+#ifndef SetupCTagsOpts
+#define SetupCTagsOpts /*none*/
+#endif
+GenerateOptionsMakeVars(CTAGS,OPTS,AllProjectsCTagsOpts,PlatformCTagsOpts,ProjectCTagsOpts,SetupCTagsOpts)
+CTAGSFLAGS = $(GLUED_CTAGS_OPTS)
+
+#ifndef AllProjectsPerlTagsOpts
+#define AllProjectsPerlTagsOpts /*none*/
+#endif
+#ifndef PlatformPerlTagsOpts
+#define PlatformPerlTagsOpts /*none*/
+#endif
+#ifndef ProjectPerlTagsOpts
+#define ProjectPerlTagsOpts /*none*/
+#endif
+#ifndef SetupPerlTagsOpts
+#define SetupPerlTagsOpts /*none*/
+#endif
+GenerateOptionsMakeVars(PERLTAGS,OPTS,AllProjectsPerlTagsOpts,PlatformPerlTagsOpts,ProjectPerlTagsOpts,SetupPerlTagsOpts)
+PERLTAGSFLAGS = $(GLUED_PERLTAGS_OPTS)
+
+/* and for "runstdtest" */
+
+#ifndef AllProjectsRunStdTestOpts
+#define AllProjectsRunStdTestOpts /*none*/
+#endif
+#ifndef PlatformRunStdTestOpts
+#define PlatformRunStdTestOpts /*none*/
+#endif
+#ifndef ProjectRunStdTestOpts
+#define ProjectRunStdTestOpts /*none*/
+#endif
+#ifndef SetupRunStdTestOpts
+#define SetupRunStdTestOpts /*none*/
+#endif
+GenerateOptionsMakeVars(RUNSTDTEST,OPTS,AllProjectsRunStdTestOpts,PlatformRunStdTestOpts,ProjectRunStdTestOpts,SetupRunStdTestOpts)
+RUNSTDTEST_FLAGS = $(GLUED_RUNSTDTEST_OPTS)
+
+/* CPP definitions for #defines */
+
+#ifndef AllProjectsJmakeDefines
+#define AllProjectsJmakeDefines /*none*/
+#endif
+#ifndef PlatformJmakeDefines
+#define PlatformJmakeDefines /**/
+#endif /* PlatformJmakeDefines */
+#ifndef ProjectJmakeDefines
+#define ProjectJmakeDefines /*none*/
+#endif
+#ifndef SetupJmakeDefines
+#define SetupJmakeDefines /*none*/
+#endif
+GenerateOptionsMakeVars(JMAKE,DEFINES,AllProjectsJmakeDefines,PlatformJmakeDefines,ProjectJmakeDefines,SetupJmakeDefines)
+JMAKEFLAGS = $(GLUED_JMAKE_DEFINES)
diff --git a/web/glasgow/lit2x-0.16/mkworld/utils-GEN.ljm b/web/glasgow/lit2x-0.16/mkworld/utils-GEN.ljm
new file mode 100644
index 0000000000..6d3faecda9
--- /dev/null
+++ b/web/glasgow/lit2x-0.16/mkworld/utils-GEN.ljm
@@ -0,0 +1,1130 @@
+%************************************************************************
+%* *
+\section[mkworld-utils-GEN]{General stuff about ``utilities''}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsection[mkworld-utils-what]{What they are (intro)}
+%* *
+%************************************************************************
+
+%************************************************************************
+%* *
+\subsection[mkworld-utils-where]{Where they are}
+%* *
+%************************************************************************
+
+Generally-useful utils that are pre-supposed (but a project might want
+diff ones).
+
+For @ar@, the \tr{l} means to use \tr{.} for temp files; the \tr{s} in
+the SystemV-ish case takes the place of \tr{ranlib}.
+\begin{code}
+#ifndef ArCmd
+#if HasSysVishArAndRanlib == YES
+#define ArCmd ar clqs
+#else
+#define ArCmd ar clq
+#endif
+#endif
+AR = ArCmd
+\end{code}
+
+\begin{code}
+#ifndef ArchCmd
+#define ArchCmd arch
+#endif
+ARCH_CMD = ArchCmd
+
+#ifndef MachCmd
+#define MachCmd mach
+#endif
+MACH_CMD = MachCmd
+
+#ifndef AsCmd
+#define AsCmd as
+#endif
+AS = AsCmd
+
+#ifndef WhatGccIsCalled /* version 2.n, please */
+#define WhatGccIsCalled gcc
+#endif
+
+#ifndef CcCmd
+#if (HaveGcc == YES) && (UseGcc == YES)
+#define CcCmd WhatGccIsCalled
+#else
+#define CcCmd cc
+#endif /* ! HaveGcc etc */
+#endif /* CcCmd */
+CC = CcCmd
+
+#ifndef CompressCmd
+#define CompressCmd compress
+#endif
+COMPRESS = CompressCmd
+
+#ifndef CpCmd
+#define CpCmd cp
+#endif
+CP = CpCmd
+
+#ifndef CppCmd
+#define CppCmd /lib/cpp
+#endif
+#ifndef PreProcessCmd
+#define PreProcessCmd CcCmd -E
+#endif
+CPP = CppCmd $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) /* simple filters */
+PREPROCESSCMD = PreProcessCmd $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) /* preferred; mdep */
+
+#ifndef InstallCmd
+#define InstallCmd install
+#endif /* InstallCmd */
+INSTALL = InstallCmd
+#ifndef InstallingByDefault
+#define InstallingByDefault 0
+#endif
+INSTALLING = InstallingByDefault
+
+#ifndef LexCmd
+#ifdef UseFlexForLexCmd
+#define LexCmd flex
+#else
+#define LexCmd lex
+#endif
+#endif
+#ifndef FlexCmd
+#define FlexCmd flex -s
+#endif
+LEX = LexCmd
+FLEX = FlexCmd $(EXTRA_FLEX_FLAGS) /* this is asking for it... */
+
+/* the installed Haskell compiler */
+#ifndef HaskellCompileCmd
+#define HaskellCompileCmd hc
+#endif
+HC = HaskellCompileCmd
+
+#ifndef LaTeXCmd
+#define LaTeXCmd latex
+#endif
+LATEX = LaTeXCmd
+/* see also the LaTeX-wrapper script, LTX, in AllProjects */
+
+#ifndef LdCmd
+#define LdCmd ld
+#endif
+LD = LdCmd
+
+#ifndef LintCmd
+#define LintCmd lint
+#endif
+LINT = LintCmd
+
+#ifndef LnCmd
+#define LnCmd ln -s
+#endif /* LnCmd */
+LN = LnCmd
+
+#ifndef MakeCmd
+#define MakeCmd make
+#endif
+/* this might be useful at some point ... */
+#ifndef MakeCmdIsGnuMake
+#define MakeCmdIsGnuMake NO
+#endif
+MAKE = MakeCmd
+
+#ifndef MvCmd
+#define MvCmd mv
+#endif
+MV = MvCmd
+
+#ifndef NroffCmd
+#define NroffCmd nroff
+#endif
+#ifndef ManMacros
+#define ManMacros -man
+#endif
+#ifndef MsMacros
+#define MsMacros -ms
+#endif
+NROFF = NroffCmd
+MANMACROS = ManMacros
+MSMACROS = MsMacros
+
+#ifndef PerlCmd
+#define PerlCmd /usr/bin/perl
+#endif
+PERL = PerlCmd
+
+#ifndef PicCmd
+#define PicCmd pic
+#endif
+PIC = PicCmd
+
+#ifndef PrinterCmd
+#define PrinterCmd lpr
+#endif
+PRINTER = PrinterCmd
+
+#ifndef RanlibCmd
+#if HasSysVishArAndRanlib == YES
+#define RanlibCmd /bin/true /* does nothing */
+#else
+#define RanlibCmd ranlib
+#endif
+#endif
+RANLIB = RanlibCmd
+
+#ifndef RmCmd
+#define RmCmd rm -f
+#endif
+RM = RmCmd
+/* a project may want to override CLEAN_CMD */
+
+/* see the comment about not having #*, under CleanTarget rule in Jmake.rules */
+/* ToDo: what about bbl files? */
+#ifndef FilesToClean
+#define FilesToClean *.CKP *.ln *.BAK *.bak *.o core a.out errs ,* *.a .emacs_* tags TAGS \
+ *.ind *.ilg *.idx *.idx-prev *.aux *.aux-prev *.dvi *.log *.toc *.lot *.lof \
+ *.blg *.info *.itxi *.itex *.cb
+#endif
+/* you can override this in various ways... */
+/* Real Men (TM) will have the following in their veryclean stuff:
+ Makefile
+ .??*~ *~ (emacs backup files)
+ *.tex *.texi
+ *.lex.c *.yacc.c [however this should be done...]
+ *.orig *.rej (patch droppings)
+*/
+#ifndef ExtraFilesToBeVeryClean
+#define ExtraFilesToBeVeryClean .??*~ *~ *.orig *.rej
+#endif
+CLEAN_CMD = $(RM) FilesToClean
+STD_VERY_CLEAN = ExtraFilesToBeVeryClean
+
+#ifndef SoelimCmd
+#ifndef UseSoelim
+#define SoelimCmd cat /* fake it */
+#else
+#if defined(UseInstalledUtils)
+#define SoelimCmd soelim
+#else
+#define SoelimCmd $(SOELIMSRC)/soelim
+#endif /* UseInstalledUtils */
+#endif /* UseSoelim */
+#endif /* SoelimCmd */
+SOELIM = SoelimCmd
+
+#ifndef CTagsCmd
+#define CTagsCmd $(ETAGS)
+#endif
+CTAGS = CTagsCmd
+
+#ifndef StripCmd
+#define StripCmd strip
+#endif
+STRIP = StripCmd
+
+#ifndef TblCmd
+#define TblCmd tbl
+#endif
+TBL = TblCmd
+
+#ifndef TeXCmd
+#define TeXCmd tex
+#endif
+TEX = TeXCmd
+
+#ifndef TgrindCmd
+#define TgrindCmd tgrind
+#endif
+/* the program that really does the tgrind'ing */
+#ifndef TgrindHelperCmd
+#define TgrindHelperCmd /usr/local/lib/tgrind/tfontedpr
+#endif
+TGRIND = TgrindCmd
+TGRIND_HELPER = TgrindHelperCmd
+
+#ifndef TibCmd
+#define TibCmd tib /* you could define this to "cat" if you don't have "tib"... */
+#endif /* (I didn't say it would be pretty...) */
+TIB = TibCmd
+
+#ifndef TimeCmd
+#define TimeCmd time
+#endif
+TIME = TimeCmd
+
+#ifndef TroffCmd
+#define TroffCmd troff
+#endif
+TROFF = TroffCmd
+
+#ifndef YaccCmd
+#define YaccCmd yacc
+#endif
+YACC = YaccCmd
+
+/* Note on the <pgm>NeededHere rules: they don't really check that
+ * the program elsewhere in the sources is really up-to-date;
+ * they really just arrange to go build it if it doesn't exist at all.
+ * This is usually good enough.
+ */
+
+/* general idea behind these things (__* is an internal macro) ... */
+
+#ifndef __SomeUtilNeededHere
+#if defined(UseInstalledUtils)
+#define __SomeUtilNeededHere(target,neededthing,neededthingsrcdir,neededthingmaketarg) /**/
+#else
+#define __SomeUtilNeededHere(target,neededthing,neededthingsrcdir,neededthingmaketarg) @@\
+ @@\
+target:: neededthing @@\
+ @@\
+neededthing: @@\
+ @echo "checking $@ over in" neededthingsrcdir "first..."; \ @@\
+ cd neededthingsrcdir; $(MAKE) neededthingmaketarg; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)"
+#endif /* ! UseInstalledUtils */
+#endif /* __SomeUtilNeededHere */
+
+/*# ------------------------------------------------ */
+/*# OTHER GENERALLY-USEFUL UTILS (w/ source provided) */
+
+#ifndef UseInstalledUtils
+UTILSRC = $(TOP)/grasp-utils
+SCRIPTSRC = $(UTILSRC)/scripts
+#endif
+
+/*# Configuration stuff (jmake, its friends and templates) */
+
+#ifndef JmkmfCmd
+#if defined(UseInstalledUtils)
+#define JmkmfCmd jmkmf
+#else
+#define JmkmfCmd jmkmf_used_only_with_installed_utils
+#endif
+#endif
+
+#ifndef JrestoredepsCmd
+#if defined(UseInstalledUtils)
+#define JrestoredepsCmd jrestoredeps
+#else
+#define JrestoredepsCmd $(JMAKESRC)/jrestoredeps
+#endif
+#endif
+
+#ifndef JmakeCmd
+#if defined(UseInstalledUtils)
+#define JmakeCmd jmake
+#else
+#define JmakeCmd $(JMAKESRC)/jmake
+#endif
+#endif
+/*
+ * JmakeNeededHere -- generate rules to compile jmake if its source is
+ * within this project's source tree.
+ *
+ * [doesn't quite fit std pattern in __SomeUtilNeededHere]
+ */
+#ifndef JmakeNeededHere
+#if defined(UseInstalledUtils)
+#define JmakeNeededHere(target) /**/
+#else
+#define JmakeNeededHere(target) @@\
+target:: $(JMAKE) @@\
+ @@\
+$(JMAKE): @@\
+ @(cd $(JMAKESRC); if [ -f Makefile ]; then \ @@\
+ echo "checking $@ in $(JMAKESRC) first..."; $(MAKE) all; else \ @@\
+ echo "bootstrapping $@ from Makefile.BOOT in $(JMAKESRC) first..."; \ @@\
+ $(MAKE) -f Makefile.BOOT BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)")
+#endif /* ! UseInstalledUtils */
+#endif /* JmakeNeededHere */
+
+JMKMF = JmkmfCmd
+JRESTOREDEPS = JrestoredepsCmd
+JMAKE = JmakeCmd
+
+/* the project config dir is assumed to be relative to $(TOP) */
+
+#if defined(UseInstalledUtils)
+#if defined(HaveProjectMkworldDir)
+JMAKE_CMD = $(JMKMF) -P $(PROJECTLABEL) -S $(SETUPLABEL) -C $(PROJ_MKWORLD_DIR) - $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#else
+JMAKE_CMD = $(JMKMF) -P $(PROJECTLABEL) -S $(SETUPLABEL) - $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#endif /* !HaveProjectMkworldDir */
+
+#else /* ! using installed jmake */
+JMAKESRC = $(TOP)/mkworld
+
+#if ProjectIsNone == YES
+#define ProjectJmFiles /*nothing*/
+#define SetupJmFiles /*nothing*/
+#else /* have a project... */
+#define ProjectJmFiles \
+ $(PROJ_MKWORLD_DIR)/site-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/only4-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/suffixes-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/macros-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/utils-$(PROJECTLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/install-$(PROJECTLABEL).jm
+
+#if SetupIsStd == YES
+#define SetupJmFiles /*nothing*/
+#else /* have project & a setup... */
+#define SetupJmFiles \
+ $(PROJ_MKWORLD_DIR)/site-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/only4-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/suffixes-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/macros-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/utils-$(PROJECTLABEL)-$(SETUPLABEL).jm \
+ $(PROJ_MKWORLD_DIR)/install-$(PROJECTLABEL)-$(SETUPLABEL).jm
+#endif
+#endif
+MYJCONFIGFILES = $(JMAKESRC)/TEMPLATE.jm \
+ $(JMAKESRC)/plat-TRIGGERS.jm \
+ $(JMAKESRC)/PlatformFile \
+ $(JMAKESRC)/plat-DEF.jm \
+ $(JMAKESRC)/site.jm \
+ $(JMAKESRC)/site-DEF.jm \
+ $(JMAKESRC)/suffixes-GEN.jm \
+ $(JMAKESRC)/macros-GEN.jm \
+ $(JMAKESRC)/utils-GEN.jm \
+ $(JMAKESRC)/install-GEN.jm ProjectJmFiles SetupJmFiles
+
+#if defined(HaveProjectMkworldDir)
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -P $(PROJECTLABEL) -S $(SETUPLABEL) -C $(NEWTOP)$(PROJ_MKWORLD_DIR) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#else
+JMAKE_CMD = $(NEWTOP)$(JMAKE) -P $(PROJECTLABEL) -S $(SETUPLABEL) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) $(JMAKEFLAGS)
+#endif /* ! HaveProjectMkworldDir */
+#endif /* ! using installed jmake */
+
+
+/*# GNU info system [hacked] */
+
+#ifndef InfoCmd
+#if defined(UseInstalledUtils)
+#define InfoCmd info
+#else
+#define InfoCmd $(INFOSRC)/info
+#endif
+#endif
+#ifndef MakeinfoCmd
+#if defined(UseInstalledUtils)
+#define MakeinfoCmd makeinfo
+#else
+#define MakeinfoCmd $(INFOSRC)/makeinfo
+#endif
+#endif
+#ifndef PostMakeinfoCmd
+#if defined(UseInstalledUtils)
+#define PostMakeinfoCmd postmakeinfo
+#else
+#define PostMakeinfoCmd $(INFOSRC)/postmakeinfo
+#endif
+#endif
+#ifndef InfoStuffNeededHere
+#if defined(UseInstalledUtils)
+#define InfoStuffNeededHere(target) /**/
+#else
+#define InfoStuffNeededHere(target) \
+__SomeUtilNeededHere(target,$(INFO) $(MAKEINFO) $(POSTMAKEINFO),$(INFOSRC),all)
+#endif /* ! UseInstalledUtils */
+#endif /* InfoStuffNeededHere */
+INFO = InfoCmd /* who _knows_ where these might be ... */
+MAKEINFO = MakeinfoCmd
+POSTMAKEINFO = PostMakeinfoCmd
+#ifndef UseInstalledUtils
+INFOSRC = $(LITSRC)/info-utils
+#endif
+
+/*# literate programming system */
+#ifndef Lit2PgmCmd
+#if defined(UseInstalledUtils)
+#define Lit2PgmCmd lit2pgm
+#else
+#define Lit2PgmCmd $(LITSRC)/lit2pgm
+#endif
+#endif
+#ifndef Lit2TexiCmd
+#if defined(UseInstalledUtils)
+#define Lit2TexiCmd lit2texi
+#else
+#define Lit2TexiCmd $(LITSRC)/lit2texi
+#endif
+#endif
+#ifndef Lit2LaTeXCmd
+#if defined(UseInstalledUtils)
+#define Lit2LaTeXCmd lit2latex
+#else
+#define Lit2LaTeXCmd $(LITSRC)/lit2latex
+#endif
+#endif
+#ifndef MkDependLitCmd
+#if defined(UseInstalledUtils)
+#define MkDependLitCmd mkdependlit
+#else
+#define MkDependLitCmd $(LITSRC)/mkdependlit
+#endif
+#endif
+#ifndef Lit2ChangeLogCmd
+#if defined(UseInstalledUtils)
+#define Lit2ChangeLogCmd lit2changelog
+#else
+#define Lit2ChangeLogCmd $(LITSRC)/lit2changelog
+#endif
+#endif
+
+/* NB: this *NeededHere rule offers LIMITED guarantee that
+ the literate-programming stuff is up-to-date when used
+*/
+#ifndef LitStuffNeededHere
+#if defined(UseInstalledUtils)
+#define LitStuffNeededHere(target) /**/
+#else
+#define LitStuffNeededHere(target) \
+ @@\
+target:: $(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex $(LITSRC)/mkdependlit $(LITSRC)/lit2changelog $(LITSRC)/lit-deatify @@\
+ @@\
+$(LITSRC)/lit2pgm $(LITSRC)/lit2texi $(LITSRC)/lit2latex $(LITSRC)/mkdependlit $(LITSRC)/lit2changelog $(LITSRC)/lit-deatify: @@\
+ @(cd $(LITSRC); if [ -f lit2pgm ]; then \ @@\
+ echo "checking $@ in $(LITSRC) first..."; $(MAKE) all; else \ @@\
+ echo "bootstrapping $@ with ./lit2pgm.BOOT in $(LITSRC) first..."; \ @@\
+ $(MAKE) LIT2PGM="./lit2pgm.BOOT -Alit2pgm" lit-deatify all; fi; \ @@\
+ echo "okay, continuing in $(CURRENT_DIR)")
+#endif /* ! UseInstalledUtils */
+#endif /* LitStuffNeededHere */
+
+LIT2PGM = Lit2PgmCmd
+/* sometimes, we _must_ use the installed version of lit2pgm,
+ * e.g., for building lit2pgm itself
+ */
+LIT2TEXI = Lit2TexiCmd
+LIT2LATEX = Lit2LaTeXCmd
+MKDEPENDLIT = MkDependLitCmd
+LIT2CHANGELOG = Lit2ChangeLogCmd
+#ifndef UseInstalledUtils
+LITSRC = $(TOP)/literate
+#endif
+
+/*# mkdepend scripts for various languages */
+/*# ["mkdependlit" is under literate programming stuff above] */
+
+/* for these MkDepend things, we use the scripts only [for now] */
+
+#ifndef MkDependCSrc
+#define MkDependCSrc $(SCRIPTSRC)
+#endif
+#ifndef MkDependCCmd
+#if defined(UseInstalledUtils)
+#define MkDependCCmd mkdependC
+#else
+#define MkDependCCmd $(MKDEPENDCSRC)/mkdependC
+#endif /* ! installed */
+#endif /* MkDependCCmd */
+
+/*
+ MkdependCNeededHere -- generate rules to build the mkdependC program
+ if its source is within this project's source tree.
+
+ [kind of a weird one, for now at least]
+*/
+#ifndef MkDependCNeededHere
+#if defined(UseInstalledUtils)
+#define MkDependCNeededHere(target) /**/
+#else
+#define MkDependCNeededHere(target) \
+__SomeUtilNeededHere(target,$(MKDEPENDC),$(MKDEPENDCSRC),mkdependC)
+#endif /* UseInstalledUtils */
+#endif /* MkDependCNeededHere */
+MKDEPENDC = MkDependCCmd
+#ifndef UseInstalledUtils
+MKDEPENDCSRC = MkDependCSrc
+#endif
+
+#ifndef MkDependHSCmd /* this is the default; hope you have it! */
+#define MkDependHSCmd mkdependHS
+#endif
+#ifndef MkDependHSNeededHere /* ditto */
+#define MkDependHSNeededHere(targets) /*no such thing*/
+#endif
+MKDEPENDHS = MkDependHSCmd
+
+/* mkdependlit is with the literate stuff above */
+
+/* tags utilities */
+
+#ifndef PerlTagsSrc
+#define PerlTagsSrc $(SCRIPTSRC)
+#endif
+#if defined(UseInstalledUtils)
+#define PerlTagsCmd perltags
+#else
+#define PerlTagsCmd $(PERLTAGSSRC)/perltags
+#endif
+
+#ifndef PerlTagsNeededHere
+#if defined(UseInstalledUtils)
+#define PerlTagsNeededHere(target) /**/
+#else
+#define PerlTagsNeededHere(target) \
+__SomeUtilNeededHere(target,$(PERLTAGS),$(PERLTAGSSRC),perltags)
+#endif /* UseInstalledUtils */
+#endif /* PerlTagsNeededHere */
+PERLTAGS = PerlTagsCmd
+#ifndef UseInstalledUtils
+PERLTAGSSRC = PerlTagsSrc
+#endif
+
+/*# misc utilities */
+
+#ifndef FastmakeCmd
+#if defined(UseInstalledUtils)
+#define FastmakeCmd fastmake
+#else
+#define FastmakeCmd $(FASTMAKESRC)/fastmake
+#endif
+#endif
+#ifndef FastmakeNeededHere
+#if defined(UseInstalledUtils)
+#define FastmakeNeededHere(target) /**/
+#else
+#define FastmakeNeededHere(target) \
+__SomeUtilNeededHere(target,$(FASTMAKE),$(FASTMAKESRC),fastmake)
+#endif /* ! UseInstalledUtils */
+#endif /* FastmakeNeededHere */
+FASTMAKE = FastmakeCmd
+#ifndef UseInstalledUtils
+FASTMAKESRC = $(SCRIPTSRC)
+#endif
+
+#ifndef LtxCmd
+#if defined(UseInstalledUtils)
+#define LtxCmd ltx
+#else
+#define LtxCmd $(LTXSRC)/ltx
+#endif
+#endif
+#ifndef LtxNeededHere
+#if defined(UseInstalledUtils)
+#define LtxNeededHere(target) /**/
+#else
+#define LtxNeededHere(target) \
+__SomeUtilNeededHere(target,$(LTX),$(LTXSRC),ltx)
+#endif /* ! UseInstalledUtils */
+#endif /* LtxNeededHere */
+LTX = LtxCmd /* a LaTeX-wrapper script */
+#ifndef UseInstalledUtils
+LTXSRC = $(SCRIPTSRC)
+#endif
+
+#ifndef MkdirHierCmd
+#if defined(UseInstalledUtils)
+#define MkdirHierCmd mkdirhier
+#else
+#define MkdirHierCmd $(MKDIRHIERSRC)/mkdirhier
+#endif
+#endif
+#ifndef MkdirHierNeededHere
+#if defined(UseInstalledUtils)
+#define MkdirHierNeededHere(target) /**/
+#else
+#define MkdirHierNeededHere(target) \
+__SomeUtilNeededHere(target,$(MKDIRHIER),$(MKDIRHIERSRC),mkdirhier)
+#endif /* ! UseInstalledUtils */
+#endif /* MkdirHierNeededHere */
+MKDIRHIER = MkdirHierCmd
+#ifndef UseInstalledUtils
+MKDIRHIERSRC = $(SCRIPTSRC)
+#endif
+
+/* Simon Marlow says: Lndir is sometimes dubious; if you
+ have GNU cp, define "LndirCmd" to: cp -Rsv
+*/
+#ifndef LndirCmd
+#if defined(UseInstalledUtils)
+#define LndirCmd lndir
+#else
+#define LndirCmd $(LNDIRSRC)/lndir
+#endif
+#endif
+#ifndef LndirNeededHere
+#if defined(UseInstalledUtils)
+#define LndirNeededHere(target) /**/
+#else
+#define LndirNeededHere(target) \
+__SomeUtilNeededHere(target,$(LNDIR),$(LNDIRSRC),lndir)
+#endif /* ! UseInstalledUtils */
+#endif /* LndirNeededHere */
+LNDIR = LndirCmd
+#ifndef UseInstalledUtils
+LNDIRSRC = $(SCRIPTSRC)
+#endif
+
+#ifndef MsubCmd
+#if defined(UseInstalledUtils)
+#define MsubCmd msub
+#else
+#define MsubCmd $(MSUBSRC)/msub
+#endif /* ! installed */
+#endif /* MsubCmd */
+/* MsubNeededHere - generate rules to build the msub program
+ if its source is within this project's source tree. This rule
+ should be included manually once in each Jmakefile that generates
+ targets with msub. (Ideally it would be invoked automatically from
+ within each msub-target-generating rule, but then you have a million
+ sets of these rules in the Makefile. Ugh. This could be avoided if
+ there were some way for a rule to void itself after being invoked
+ once.)
+*/
+#ifndef MsubNeededHere
+#if defined(UseInstalledUtils)
+#define MsubNeededHere(target) /**/
+#else
+#define MsubNeededHere(target) \
+__SomeUtilNeededHere(target,$(MSUB),$(MSUBSRC),msub)
+#endif /* ! UseInstalledUtils */
+#endif /* MsubNeededHere */
+MSUB = MsubCmd
+#ifndef UseInstalledUtils
+MSUBSRC = $(UTILSRC)/msub
+#endif
+
+#ifndef EtagsCmd
+#if defined(UseInstalledUtils)
+#define EtagsCmd etags
+#else
+#define EtagsCmd $(ETAGSSRC)/etags
+#endif /* ! installed */
+#endif /* EtagsCmd */
+#ifndef EtagsNeededHere
+#if defined(UseInstalledUtils)
+#define EtagsNeededHere(target) /**/
+#else
+#define EtagsNeededHere(target) \
+__SomeUtilNeededHere(target,$(ETAGS),$(ETAGSSRC),etags)
+#endif /* ! UseInstalledUtils */
+#endif /* EtagsNeededHere */
+ETAGS = EtagsCmd
+#ifndef UseInstalledUtils
+ETAGSSRC = $(UTILSRC)/etags
+#endif
+
+#ifndef VerbatimCmd
+#if defined(UseInstalledUtils)
+#define VerbatimCmd verbatim
+#else
+#define VerbatimCmd $(VERBATIMSRC)/verbatim
+#endif /* ! installed */
+#endif /* VerbatimCmd */
+#ifndef VerbatimNeededHere
+#if defined(UseInstalledUtils)
+#define VerbatimNeededHere(target) /**/
+#else
+#define VerbatimNeededHere(target) \
+__SomeUtilNeededHere(target,$(VERBATIM),$(VERBATIMSRC),verbatim)
+#endif /* ! UseInstalledUtils */
+#endif /* VerbatimNeededHere */
+VERBATIM = VerbatimCmd
+#ifndef UseInstalledUtils
+VERBATIMSRC = $(UTILSRC)/verbatim
+#endif
+
+#ifndef RunStdTestCmd
+#if defined(UseInstalledUtils)
+#define RunStdTestCmd runstdtest
+#else
+#define RunStdTestCmd $(RUNSTDTESTSRC)/runstdtest
+#endif
+#endif
+#ifndef RunStdTestNeededHere
+#if defined(UseInstalledUtils)
+#define RunStdTestNeededHere(target) /**/
+#else
+#define RunStdTestNeededHere(target) \
+__SomeUtilNeededHere(target,$(RUNSTDTEST),$(RUNSTDTESTSRC),runstdtest)
+#endif /* ! UseInstalledUtils */
+#endif /* RunStdTestNeededHere */
+RUNSTDTEST = RunStdTestCmd
+#ifndef UseInstalledUtils
+RUNSTDTESTSRC = $(SCRIPTSRC)
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mkworld-utils-flags]{Feeding flags to them}
+%* *
+%************************************************************************
+
+\begin{code}
+/* for the whole nasty business of flags for programs,
+ some naming conventions are worth remembering; for program <foo>:
+
+ <foo>FLAGS what is actually passed to <foo>; usually
+ built from pieces below
+
+ ALLPROJ_<foo>_<things> <things> needed for _all_ runs of <foo>;
+ probably set in one of the AllProject*
+ config files.
+ PLAT_<foo>_<things> <things> (options, defines, etc.) needed for
+ all runs of <foo> *on this platform*;
+ probably set in <platform>.cf.
+ PROJ_<foo>_<things> <things> needed for all runs of <foo>
+ related to this project; probably set in
+ one of the Project-* config files.
+ <foo>_<things> <things> needed for runs of <foo> in this
+ directory; set in its Jmakefile.
+ EXTRA_<foo>_<things> name reserved for adding <things> from the
+ command line.
+ GLUED_<foo>_<things> all the above, glued together; not for
+ human use.
+
+ <foo>_OPTS the usual name for options
+ <foo>_DEFINES CPP #defines
+ <foo>_INCLUDES CPP #includes
+ <foo>_IMPORTS Haskell "import"s
+
+ As a contrived example, the "makeinfo" program is usually called
+ with the $(MAKEINFOFLAGS), which would likely be put together as...
+
+ ALLPROJ_MAKEINFO_OPTS =
+ PLAT_MAKEINFO_OPTS =
+ PROJ_MAKEINFO_OPTS =
+ MAKEINFO_OPTS =
+ EXTRA_MAKEINFO_OPTS =
+ GLUED_MAKEINFO_OPTS =
+ MAKEINFOFLAGS = $(GLUED_MAKEINFO_OPTS)
+
+ and used as...
+
+ $(MAKEINFO) $(MAKEINFOFLAGS) ...
+
+ The related CPP names are as you would expect: e.g.,
+ ProjectMakeinfoOpts for PROJ_MAKEINFO_OPTS, ...
+
+ For systems of interacting programs (e.g., cpp, cc, lint, as, and ld),
+ things can be [considerably] messier.
+
+*/
+
+/* CPP definitions for CPP #includes; -I must be explicit */
+
+/* I have not separated use of CPP w/ CC vs standalone... */
+
+#ifndef AllProjectsCppIncludes
+#define AllProjectsCppIncludes /*none*/
+#endif
+#ifndef PlatformCppIncludes
+#define PlatformCppIncludes /*none*/
+#endif
+#ifndef ProjectCppIncludes
+#define ProjectCppIncludes /*none*/
+#endif
+#ifndef SetupCppIncludes
+#define SetupCppIncludes /*none*/
+#endif
+GenerateOptionsMakeVars(CPP,INCLUDES,AllProjectsCppIncludes,PlatformCppIncludes,ProjectCppIncludes,SetupCppIncludes)
+
+/* CPP definitions for #defines */
+
+#ifndef AllProjectsCppDefines
+#define AllProjectsCppDefines /*none*/
+#endif
+#ifndef PlatformCppDefines
+#define PlatformCppDefines /**/
+#endif /* PlatformCppDefines */
+#ifndef ProjectCppDefines
+#define ProjectCppDefines /*none*/
+#endif
+#ifndef SetupCppDefines
+#define SetupCppDefines /*none*/
+#endif
+GenerateOptionsMakeVars(CPP,DEFINES,AllProjectsCppDefines,PlatformCppDefines,ProjectCppDefines,SetupCppDefines)
+
+/*# C-compiler (and cpp ... and lint) options */
+
+#ifndef AllProjectsCcOpts
+#define AllProjectsCcOpts /*none*/
+#endif
+#ifndef PlatformCcOpts
+#define PlatformCcOpts /*none*/
+#endif
+#ifndef ProjectCcOpts
+#define ProjectCcOpts /*none*/
+#endif
+#ifndef SetupCcOpts
+#define SetupCcOpts /*none*/
+#endif
+GenerateOptionsMakeVars(CC,OPTS,AllProjectsCcOpts,PlatformCcOpts,ProjectCcOpts,SetupCcOpts)
+
+CFLAGS = $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES) $(GLUED_CC_OPTS)
+
+/*# Haskell compiler (and cpp ... and lint) options */
+
+#ifndef AllProjectsHcOpts
+#define AllProjectsHcOpts /*none*/
+#endif
+#ifndef PlatformHcOpts
+#define PlatformHcOpts /*none*/
+#endif
+#ifndef ProjectHcOpts
+#define ProjectHcOpts /*none*/
+#endif
+#ifndef SetupHcOpts
+#define SetupHcOpts /*none*/
+#endif
+GenerateOptionsMakeVars(HC,OPTS,AllProjectsHcOpts,PlatformHcOpts,ProjectHcOpts,SetupHcOpts)
+
+#ifndef AllProjectsHcImports
+#define AllProjectsHcImports /*none*/
+#endif
+#ifndef PlatformHcImports
+#define PlatformHcImports /*none*/
+#endif
+#ifndef ProjectHcImports
+#define ProjectHcImports /*none*/
+#endif
+#ifndef SetupHcImports
+#define SetupHcImports /*none*/
+#endif
+GenerateOptionsMakeVars(HC,IMPORTS,AllProjectsHcImports,PlatformHcImports,ProjectHcImports,SetupHcImports)
+HCFLAGS = $(GLUED_HC_IMPORTS) $(GLUED_CPP_DEFINES) $(GLUED_HC_OPTS)
+
+/*# linker options */
+
+#ifndef AllProjectsLdOpts
+#define AllProjectsLdOpts /*none*//* -X -r "combine" flags (?) */
+#endif
+#ifndef PlatformLdOpts
+#define PlatformLdOpts /*none*/
+#endif
+#ifndef ProjectLdOpts
+#define ProjectLdOpts /*none*/
+#endif
+#ifndef SetupLdOpts
+#define SetupLdOpts /*none*/
+#endif
+#ifndef AllProjectsLdLibraries
+#define AllProjectsLdLibraries /*none*/
+#endif
+#ifndef PlatformLdLibraries
+#define PlatformLdLibraries /*none*/
+#endif
+#ifndef ProjectLdLibraries
+#define ProjectLdLibraries /*none*/
+#endif
+#ifndef SetupLdLibraries
+#define SetupLdLibraries /*none*/
+#endif
+GenerateOptionsMakeVars(LD,OPTS,AllProjectsLdOpts,PlatformLdOpts,ProjectLdOpts,SetupLdOpts)
+GenerateOptionsMakeVars(LD,LIBRARIES,AllProjectsLdLibraries,PlatformLdLibraries,ProjectLdLibraries,SetupLdLibraries)
+LDOPTIONS = $(GLUED_LD_OPTS) /* ToDo: and the libraries ? */
+
+/* lint stuff not tidied up yet */
+
+#ifndef LintLibFlag
+#define LintLibFlag -C
+#endif
+#ifndef LintOpts
+#define LintOpts -axz
+#endif
+LINTLIBFLAG = LintLibFlag
+LINTOPTS = LintOpts
+LINTFLAGS = $(LINTOPTS) -DLINT $(GLUED_CPP_INCLUDES) $(GLUED_CPP_DEFINES)
+
+/*# literate-stuff options */
+
+/* some options are common (general) to all lit2* pgms; others specific */
+
+#ifndef AllProjectsGenLitOpts
+#define AllProjectsGenLitOpts /*none*/
+#endif
+#ifndef PlatformGenLitOpts
+#define PlatformGenLitOpts /*none*/
+#endif
+#ifndef ProjectGenLitOpts
+#define ProjectGenLitOpts /*none*/
+#endif
+#ifndef SetupGenLitOpts
+#define SetupGenLitOpts /*none*/
+#endif
+GenerateOptionsMakeVars(GENLIT,OPTS,AllProjectsGenLitOpts,PlatformGenLitOpts,ProjectGenLitOpts,SetupGenLitOpts)
+
+#ifndef AllProjectsLit2pgmOpts
+#define AllProjectsLit2pgmOpts /*none*/
+#endif
+#ifndef PlatformLit2pgmOpts
+#define PlatformLit2pgmOpts /*none*/
+#endif
+#ifndef ProjectLit2pgmOpts
+#define ProjectLit2pgmOpts /*none*/
+#endif
+#ifndef SetupLit2pgmOpts
+#define SetupLit2pgmOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2PGM,OPTS,AllProjectsLit2pgmOpts,PlatformLit2pgmOpts,ProjectLit2pgmOpts,SetupLit2pgmOpts)
+#ifndef AllProjectsLit2texiOpts
+#define AllProjectsLit2texiOpts /*none*/
+#endif
+#ifndef PlatformLit2texiOpts
+#define PlatformLit2texiOpts /*none*/
+#endif
+#ifndef ProjectLit2texiOpts
+#define ProjectLit2texiOpts /*none*/
+#endif
+#ifndef SetupLit2texiOpts
+#define SetupLit2texiOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2TEXI,OPTS,AllProjectsLit2texiOpts,PlatformLit2texiOpts,ProjectLit2texiOpts,SetupLit2texiOpts)
+#ifndef AllProjectsLit2latexOpts
+#define AllProjectsLit2latexOpts /*none*/
+#endif
+#ifndef PlatformLit2latexOpts
+#define PlatformLit2latexOpts /*none*/
+#endif
+#ifndef ProjectLit2latexOpts
+#define ProjectLit2latexOpts /*none*/
+#endif
+#ifndef SetupLit2latexOpts
+#define SetupLit2latexOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2LATEX,OPTS,AllProjectsLit2latexOpts,PlatformLit2latexOpts,ProjectLit2latexOpts,SetupLit2latexOpts)
+#ifndef AllProjectsLit2changelogOpts
+#define AllProjectsLit2changelogOpts /*none*/
+#endif
+#ifndef PlatformLit2changelogOpts
+#define PlatformLit2changelogOpts /*none*/
+#endif
+#ifndef ProjectLit2changelogOpts
+#define ProjectLit2changelogOpts /*none*/
+#endif
+#ifndef SetupLit2changelogOpts
+#define SetupLit2changelogOpts /*none*/
+#endif
+GenerateOptionsMakeVars(LIT2CHANGELOG,OPTS,AllProjectsLit2changelogOpts,PlatformLit2changelogOpts,ProjectLit2changelogOpts,SetupLit2changelogOpts)
+#ifndef AllProjectsMkDependLitOpts
+#define AllProjectsMkDependLitOpts /*none*/
+#endif
+#ifndef PlatformMkDependLitOpts
+#define PlatformMkDependLitOpts /*none*/
+#endif
+#ifndef ProjectMkDependLitOpts
+#define ProjectMkDependLitOpts /*none*/
+#endif
+#ifndef SetupMkDependLitOpts
+#define SetupMkDependLitOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDLIT,OPTS,AllProjectsMkDependLitOpts,PlatformMkDependLitOpts,ProjectMkDependLitOpts,SetupMkDependLitOpts)
+
+LIT2PGMFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2PGM_OPTS)
+LIT2TEXIFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2TEXI_OPTS)
+LIT2LATEXFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2LATEX_OPTS)
+LIT2CHANGELOGFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_LIT2CHANGELOG_OPTS)
+MKDEPENDLITFLAGS = $(GLUED_GENLIT_OPTS) $(GLUED_MKDEPENDLIT_OPTS)
+
+/* same for other MkDepend things */
+
+#ifndef AllProjectsMkDependCOpts
+#define AllProjectsMkDependCOpts /*none*/
+#endif
+#ifndef PlatformMkDependCOpts
+#define PlatformMkDependCOpts /*none*/
+#endif
+#ifndef ProjectMkDependCOpts
+#define ProjectMkDependCOpts /*none*/
+#endif
+#ifndef SetupMkDependCOpts
+#define SetupMkDependCOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDC,OPTS,AllProjectsMkDependCOpts,PlatformMkDependCOpts,ProjectMkDependCOpts,SetupMkDependCOpts)
+MKDEPENDCFLAGS = $(GLUED_MKDEPENDC_OPTS)
+
+#ifndef AllProjectsMkDependHSOpts
+#define AllProjectsMkDependHSOpts /*none*/
+#endif
+#ifndef PlatformMkDependHSOpts
+#define PlatformMkDependHSOpts /*none*/
+#endif
+#ifndef ProjectMkDependHSOpts
+#define ProjectMkDependHSOpts /*none*/
+#endif
+#ifndef SetupMkDependHSOpts
+#define SetupMkDependHSOpts /*none*/
+#endif
+GenerateOptionsMakeVars(MKDEPENDHS,OPTS,AllProjectsMkDependHSOpts,PlatformMkDependHSOpts,ProjectMkDependHSOpts,SetupMkDependHSOpts)
+MKDEPENDHSFLAGS = $(GLUED_MKDEPENDHS_OPTS)
+
+/* same for tags stuff */
+
+#ifndef AllProjectsCTagsOpts
+#define AllProjectsCTagsOpts -e -w /* emacs-style; no warnings */
+#endif
+#ifndef PlatformCTagsOpts
+#define PlatformCTagsOpts /*none*/
+#endif
+#ifndef ProjectCTagsOpts
+#define ProjectCTagsOpts /*none*/
+#endif
+#ifndef SetupCTagsOpts
+#define SetupCTagsOpts /*none*/
+#endif
+GenerateOptionsMakeVars(CTAGS,OPTS,AllProjectsCTagsOpts,PlatformCTagsOpts,ProjectCTagsOpts,SetupCTagsOpts)
+CTAGSFLAGS = $(GLUED_CTAGS_OPTS)
+
+#ifndef AllProjectsPerlTagsOpts
+#define AllProjectsPerlTagsOpts /*none*/
+#endif
+#ifndef PlatformPerlTagsOpts
+#define PlatformPerlTagsOpts /*none*/
+#endif
+#ifndef ProjectPerlTagsOpts
+#define ProjectPerlTagsOpts /*none*/
+#endif
+#ifndef SetupPerlTagsOpts
+#define SetupPerlTagsOpts /*none*/
+#endif
+GenerateOptionsMakeVars(PERLTAGS,OPTS,AllProjectsPerlTagsOpts,PlatformPerlTagsOpts,ProjectPerlTagsOpts,SetupPerlTagsOpts)
+PERLTAGSFLAGS = $(GLUED_PERLTAGS_OPTS)
+
+/* and for "runstdtest" */
+
+#ifndef AllProjectsRunStdTestOpts
+#define AllProjectsRunStdTestOpts /*none*/
+#endif
+#ifndef PlatformRunStdTestOpts
+#define PlatformRunStdTestOpts /*none*/
+#endif
+#ifndef ProjectRunStdTestOpts
+#define ProjectRunStdTestOpts /*none*/
+#endif
+#ifndef SetupRunStdTestOpts
+#define SetupRunStdTestOpts /*none*/
+#endif
+GenerateOptionsMakeVars(RUNSTDTEST,OPTS,AllProjectsRunStdTestOpts,PlatformRunStdTestOpts,ProjectRunStdTestOpts,SetupRunStdTestOpts)
+RUNSTDTEST_FLAGS = $(GLUED_RUNSTDTEST_OPTS)
+
+/* CPP definitions for #defines */
+
+#ifndef AllProjectsJmakeDefines
+#define AllProjectsJmakeDefines /*none*/
+#endif
+#ifndef PlatformJmakeDefines
+#define PlatformJmakeDefines /**/
+#endif /* PlatformJmakeDefines */
+#ifndef ProjectJmakeDefines
+#define ProjectJmakeDefines /*none*/
+#endif
+#ifndef SetupJmakeDefines
+#define SetupJmakeDefines /*none*/
+#endif
+GenerateOptionsMakeVars(JMAKE,DEFINES,AllProjectsJmakeDefines,PlatformJmakeDefines,ProjectJmakeDefines,SetupJmakeDefines)
+JMAKEFLAGS = $(GLUED_JMAKE_DEFINES)
+\end{code}