summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/cwebdir
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/cwebdir
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/cwebdir')
-rw-r--r--Build/source/texk/web2c/cwebdir/Makefile195
-rw-r--r--Build/source/texk/web2c/cwebdir/README98
-rw-r--r--Build/source/texk/web2c/cwebdir/c++lib.w85
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-amiga.ch17
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-bs.ch229
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-mac.ch150
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-man.ch22
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-os2.ch24
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-pc.ch33
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-ql.ch332
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-vms.ch81
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-w2c.ch620
-rw-r--r--Build/source/texk/web2c/cwebdir/comm-w32.ch94
-rw-r--r--Build/source/texk/web2c/cwebdir/common.c1242
-rw-r--r--Build/source/texk/web2c/cwebdir/common.h192
-rw-r--r--Build/source/texk/web2c/cwebdir/common.w1418
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-bs.ch202
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-man.ch22
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-pc.ch24
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-ql.ch25
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-vms.ch35
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-w2c.ch375
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-w32.ch66
-rw-r--r--Build/source/texk/web2c/cwebdir/ctangle.c1566
-rw-r--r--Build/source/texk/web2c/cwebdir/ctangle.rc34
-rw-r--r--Build/source/texk/web2c/cwebdir/ctangle.w1554
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-bs.ch302
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-man.ch22
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-pc.ch39
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-ql.ch32
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-vms.ch37
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-w2c.ch768
-rw-r--r--Build/source/texk/web2c/cwebdir/cweav-w32.ch52
-rw-r--r--Build/source/texk/web2c/cwebdir/cweave.rc34
-rw-r--r--Build/source/texk/web2c/cwebdir/cweave.w4651
-rw-r--r--Build/source/texk/web2c/cwebdir/cweb.1138
-rw-r--r--Build/source/texk/web2c/cwebdir/cweb.el215
-rw-r--r--Build/source/texk/web2c/cwebdir/cwebmac.tex539
-rw-r--r--Build/source/texk/web2c/cwebdir/cwebman.tex1761
-rw-r--r--Build/source/texk/web2c/cwebdir/depend.mak0
-rw-r--r--Build/source/texk/web2c/cwebdir/makefile.bs60
-rw-r--r--Build/source/texk/web2c/cwebdir/prod.w307
-rw-r--r--Build/source/texk/web2c/cwebdir/readme.ql84
43 files changed, 17776 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/cwebdir/Makefile b/Build/source/texk/web2c/cwebdir/Makefile
new file mode 100644
index 00000000000..31194f46bb0
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/Makefile
@@ -0,0 +1,195 @@
+# This file is part of CWEB.
+# It is distributed WITHOUT ANY WARRANTY, express or implied.
+# Version 3.64 --- February 2002
+
+# Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
+
+# Permission is granted to make and distribute verbatim copies of this
+# document provided that the copyright notice and this permission notice
+# are preserved on all copies.
+
+# Permission is granted to copy and distribute modified versions of this
+# document under the conditions for verbatim copying, provided that the
+# entire resulting derived work is given a different name and distributed
+# under the terms of a permission notice identical to this one.
+
+#
+# Read the README file, then edit this file to reflect local conditions
+#
+
+# directory for TeX inputs (cwebmac.tex goes here)
+MACROSDIR= /usr/local/texmf/tex/generic
+
+# directory for CWEB inputs in @i files
+CWEBINPUTS= /usr/local/lib/cweb
+
+# extension for manual pages ("l" distinguishes local from system stuff)
+MANEXT= l
+#MANEXT= 1
+
+# directory for manual pages (cweb.1 goes here)
+MANDIR= /usr/man/man$(MANEXT)
+
+# destination directory for executables; must end in /
+DESTDIR= /usr/local/bin/
+
+# directory for GNU EMACS Lisp code (cweb.el goes here)
+EMACSDIR= /usr/local/emacs/lisp
+
+# Set DESTPREF to null if you want to call the executables "tangle" and "weave"
+# (probably NOT a good idea; we recommend leaving DESTPREF=c)
+DESTPREF=c
+
+# Set CCHANGES to comm-foo.ch if you need changes to common.w
+CCHANGES=
+
+# Set TCHANGES to ctang-foo.ch if you need changes to ctangle.w
+TCHANGES=
+
+# Set WCHANGES to cweav-foo.ch if you need changes to cweave.w
+WCHANGES=
+
+# We keep debugging info around, for fun, but most users don't need it
+CFLAGS = -g
+#CFLAGS = -O
+LINKFLAGS = -g
+#LINKFLAGS = -s # for smaller (stripped) executables on many UNIX systems
+
+# What C compiler are you using?
+CC = cc
+
+# RM and CP are used below in case rm and cp are aliased
+RM= /bin/rm
+CP= /bin/cp
+
+# uncomment the second line if you use pdftex to bypass .dvi files
+PDFTEX = dvipdfm
+#PDFTEX = pdftex
+
+########## You shouldn't have to change anything after this point #######
+
+CWEAVE = ./cweave
+CTANGLE = ./ctangle
+SOURCES = cweave.w common.w ctangle.w
+ALL = common.w ctangle.w cweave.w prod.w \
+ Makefile common.c common.h ctangle.c \
+ cwebman.tex cwebmac.tex comm-vms.ch ctang-vms.ch \
+ cweav-vms.ch comm-man.ch ctang-man.ch cweav-man.ch \
+ comm-pc.ch ctang-pc.ch cweav-pc.ch comm-amiga.ch \
+ comm-bs.ch ctang-bs.ch cweav-bs.ch makefile.bs \
+ comm-ql.ch ctang-ql.ch cweav-ql.ch readme.ql \
+ comm-w32.ch ctang-w32.ch cweav-w32.ch \
+ comm-os2.ch comm-mac.ch cweb.1 cweb.el c++lib.w README
+
+.SUFFIXES: .dvi .tex .w .pdf
+
+.w.tex:
+ $(CWEAVE) $*
+
+.tex.dvi:
+ tex $<
+
+.w.dvi:
+ make $*.tex
+ make $*.dvi
+
+.w.c:
+ $(CTANGLE) $*
+
+.w.o:
+ make $*.c
+ make $*.o
+
+.w.pdf:
+ make $*.tex
+ case "$(PDFTEX)" in \
+ dvipdfm ) tex "\let\pdf+ \input $*"; dvipdfm $* ;; \
+ pdftex ) pdftex $* ;; \
+ esac
+
+all: ctangle cweave
+
+cautiously: ctangle
+ $(CP) common.c SAVEcommon.c
+ ./ctangle common $(CCHANGES)
+ diff common.c SAVEcommon.c
+ $(RM) SAVEcommon.c
+ $(CP) ctangle.c SAVEctangle.c
+ ./ctangle ctangle $(TCHANGES)
+ diff ctangle.c SAVEctangle.c
+ $(RM) SAVEctangle.c
+
+SAVEctangle.c:
+ $(CP) ctangle.c SAVEctangle.c
+
+SAVEcommon.c:
+ $(CP) common.c SAVEcommon.c
+
+common.c: common.w $(CCHANGES)
+ $(CTANGLE) common $(CCHANGES)
+
+common.o: common.c
+ $(CC) $(CFLAGS) -DCWEBINPUTS=\"$(CWEBINPUTS)\" -c common.c
+
+ctangle: ctangle.o common.o
+ $(CC) $(LINKFLAGS) -o ctangle ctangle.o common.o
+
+ctangle.c: ctangle.w $(TCHANGES)
+ $(CTANGLE) ctangle $(TCHANGES)
+
+cweave: cweave.o common.o
+ $(CC) $(LINKFLAGS) -o cweave cweave.o common.o
+
+cweave.c: cweave.w $(WCHANGES)
+ $(CTANGLE) cweave $(WCHANGES)
+
+doc: $(SOURCES:.w=.dvi)
+
+usermanual: cwebman.tex cwebmac.tex
+ tex cwebman
+
+fullmanual: usermanual $(SOURCES) comm-man.ch ctang-man.ch cweav-man.ch
+ make cweave
+ ./cweave common.w comm-man.ch
+ tex common.tex
+ ./cweave ctangle.w ctang-man.ch
+ tex ctangle.tex
+ ./cweave cweave.w cweav-man.ch
+ tex cweave.tex
+
+# be sure to leave ctangle.c and common.c for bootstrapping
+clean:
+ $(RM) -f -r *~ *.o common.tex cweave.tex cweave.c ctangle.tex \
+ *.log *.dvi *.toc *.idx *.scn *.pdf core cweave ctangle
+
+install: all
+ - mkdir $(DESTDIR)
+ $(CP) cweave $(DESTDIR)$(DESTPREF)weave
+ chmod 755 $(DESTDIR)$(DESTPREF)weave
+ $(CP) ctangle $(DESTDIR)$(DESTPREF)tangle
+ chmod 755 $(DESTDIR)$(DESTPREF)tangle
+ - mkdir $(MANDIR)
+ $(CP) cweb.1 $(MANDIR)/cweb.$(MANEXT)
+ chmod 644 $(MANDIR)/cweb.$(MANEXT)
+ - mkdir $(MACROSDIR)
+ $(CP) cwebmac.tex $(MACROSDIR)
+ chmod 644 $(MACROSDIR)/cwebmac.tex
+ - mkdir $(EMACSDIR)
+ $(CP) cweb.el $(EMACSDIR)
+ chmod 644 $(EMACSDIR)/cweb.el
+ - mkdir $(CWEBINPUTS)
+ $(CP) c++lib.w $(CWEBINPUTS)
+ chmod 644 $(CWEBINPUTS)/c++lib.w
+
+floppy: $(ALL) examples
+ bar cvhf /dev/rfd0 $(ALL) examples
+ bar tvf /dev/rfd0
+ eject
+
+tags: $(ALL)
+ etags -lnone $(ALL)
+
+tarfile: $(ALL) examples
+ tar cvhf /tmp/cweb.tar $(ALL) examples
+ gzip -9 /tmp/cweb.tar
+
diff --git a/Build/source/texk/web2c/cwebdir/README b/Build/source/texk/web2c/cwebdir/README
new file mode 100644
index 00000000000..1f4add6dd09
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/README
@@ -0,0 +1,98 @@
+% This file is part of CWEB.
+% The CWEB programs by Silvio Levy are based on programs by D. E. Knuth.
+% They are distributed WITHOUT ANY WARRANTY, express or implied.
+% This README file last updated May 2000 by Don Knuth
+
+% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+% Please send comments, suggestions, etc. to levy@math.berkeley.edu.
+
+This directory contains the following files:
+
+Makefile
+README
+comm-amiga.ch
+comm-bs.ch
+comm-mac.ch
+comm-man.ch
+comm-pc.ch
+comm-ql.ch
+comm-vms.ch
+comm-w32.ch
+common.c
+common.h
+common.w
+ctang-bs.ch
+ctang-man.ch
+ctang-pc.ch
+ctang-ql.ch
+ctang-vms.ch
+ctang-w32.ch
+ctangle.c
+ctangle.w
+cweav-bs.ch
+cweav-man.ch
+cweav-pc.ch
+cweav-ql.ch
+cweav-vms.ch
+cweave-w32.ch
+cweave.w
+cweb.1
+cweb.el
+cwebmac.tex
+cwebman.tex
+examples/
+makefile.bs
+prod.w
+readme.ql
+c++lib.w
+
+The file cwebman.tex is the user manual.
+The examples directory contains additional examples of the use of CWEB.
+The files common.c and ctangle.c are used for bootstrapping.
+The file cweb.1 is a manual page.
+The file cweb.el is suggested for GNU-Emacs users.
+The file c++lib.w is for C++ users (say `@i c++lib.w' at beginning of program).
+The files *-man.ch are used if you want to make the full 239-page CWEB manual.
+The files *-bs.ch are used instead of *-pc.ch if you are doing BIG programs.
+You can use makefile.bs to make CWEB with *-bs.ch.
+The files *-ql.ch are for QDOS/SMSQ systems; see readme.ql for further info.
+The files *-w32.ch use __fastcall conventions on win32 systems.
+The file comm-mac.ch is for Macintosh conventions.
+The other files named *.ch are sample change files for local customization.
+
+IMPORTANT: Please touch *.c before proceeding.
+Then edit the opening lines of Makefile so that it has the proper
+directory information for your local system.
+
+To make ctangle and cweave say `make all'; this should produce roughly
+the following actions (possibly with harmless warning messages from cc):
+
+cc -g -w -c ctangle.c
+cc -g -w -DCWEBINPUTS=\"/usr/local/lib/cweb\" -c common.c
+cc -g -o ctangle ctangle.o common.o
+./ctangle cweave
+cc -g -w -c cweave.c
+cc -g -w -o cweave cweave.o common.o
+
+To get some reassurance that things are OK, you can say `make cautiously',
+which ensures that CTANGLE will reproduce itself. (Otherwise the source
+files common.w and ctangle.w won't actually have been used.)
+
+To install cweave and ctangle say `make install'. You probably need to
+be superuser to do this; but it's wise to `make all' first, BEFORE
+becoming superuser and saying `make install'.
+
+Note that change files for VMS, AMIGA, MAC, and PCs are provided. When you
+are first bootstrapping to a new system, you may need to edit common.c and
+ctangle.c by hand, but the vast majority of the change-file changes are
+minor refinements that are not necessary for a rudimentary ctangle.
diff --git a/Build/source/texk/web2c/cwebdir/c++lib.w b/Build/source/texk/web2c/cwebdir/c++lib.w
new file mode 100644
index 00000000000..15e59cc8851
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/c++lib.w
@@ -0,0 +1,85 @@
+@q This file defines standard C++ namespaces and classes @>
+@q Please send corrections to saroj-tamasa@@worldnet.att.net @>
+@s std int
+@s rel_ops int
+@s bitset int
+@s char_traits int
+@s deque int
+@s list int
+@s map int
+@s multimap int
+@s multiset int
+@s pair int
+@s set int
+@s stack int
+@s exception int
+@s logic_error int
+@s runtime_error int
+@s domain_error int
+@s invalid_argument int
+@s length_error int
+@s out_of_range int
+@s range_error int
+@s overflow_error int
+@s underflow_error int
+@s back_insert_iterator int
+@s front_insert_iterator int
+@s insert_iterator int
+@s reverse_iterator int
+@s istream_iterator int
+@s ostream_iterator int
+@s istreambuf_iterator int
+@s ostreambuf_iterator int
+@s iterator_traits int
+@s queue int
+@s vector int
+@s basic_string int
+@s string int
+@s auto_ptr int
+@s valarray int
+@s ios_base int
+@s basic_ios int
+@s basic_streambuf int
+@s basic_istream int
+@s basic_ostream int
+@s basic_iostream int
+@s basic_stringbuf int
+@s basic_istringstream int
+@s basic_ostringstream int
+@s basic_stringstream int
+@s basic_filebuf int
+@s basic_ifstream int
+@s basic_ofstream int
+@s basic_fstream int
+@s ctype int
+@s collate int
+@s collate_byname int
+@s streambuf int
+@s istream int
+@s ostream int
+@s iostream int
+@s stringbuf int
+@s istringstream int
+@s ostringstream int
+@s stringstream int
+@s filebuf int
+@s ifstream int
+@s ofstream int
+@s fstream int
+@s wstreambuf int
+@s wistream int
+@s wostream int
+@s wiostram int
+@s wstringbuf int
+@s wistringstream int
+@s wostringstream int
+@s wstringstream int
+@s wfilebuf int
+@s wifstream int
+@s wofstream int
+@s wfstream int
+@s streamoff int
+@s streamsize int
+@s fpos int
+@s streampos int
+@s wstreampos int
diff --git a/Build/source/texk/web2c/cwebdir/comm-amiga.ch b/Build/source/texk/web2c/cwebdir/comm-amiga.ch
new file mode 100644
index 00000000000..57e65d1ccda
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-amiga.ch
@@ -0,0 +1,17 @@
+This is the change file for CWEB's COMMON on the Amiga
+(Contributed by Tomas Rokicki, June 1993)
+
+With Lattice C 5.1, use compilation switches -b0 -r0, and ignore the
+compiler warnings. With SAS 6.0, use compilation switches Code=far Data=far.
+
+@x section 69
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"nil:"| should be used,
+@z
+
+@x section 70
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,"nil:");
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-bs.ch b/Build/source/texk/web2c/cwebdir/comm-bs.ch
new file mode 100644
index 00000000000..26f79b160d1
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-bs.ch
@@ -0,0 +1,229 @@
+Changes for code common to CTANGLE and CWEAVE, for MSDOS
+and Borland C++ 3.1 using the following options (and perhaps others):
+
+ -mc -w-pro -Ff=5000 -Z- -O-p
+
+The options -Z- and -O-p explicitly turn off optimizations that seem to be
+dangerous for the style of code in the CWEB sources. (See makefile.bs.)
+
+The main purpose of these changes is to support MSDOS with full-size arrays
+by using "huge" pointers.
+
+(This file contributed by Barry Schwartz, trashman@crud.mn.org, 28 Jun 94;
+ revised 24 Jul 94.)
+
+
+@x Section 23.
+ cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+@y
+ cur_file_name[l]='/'; /* A valid {\mc MSDOS} pathname separator */
+@z
+
+
+@x Section 27.
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@<Definitions that...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ @<More elements of |name_info| structure@>@;
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of |name_info|s */
+char byte_mem[max_bytes]; /* characters of names */
+char *byte_mem_end = byte_mem+max_bytes-1; /* end of |byte_mem| */
+name_info name_dir[max_names]; /* information about names */
+name_pointer name_dir_end = name_dir+max_names-1; /* end of |name_dir| */
+@y
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@f huge extern
+
+@<Definitions that...@>=
+typedef struct name_info {
+ char huge* byte_start; /* beginning of the name in |byte_mem| */
+ @<More elements of |name_info| structure@>@;
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of |name_info|s */
+char huge byte_mem[max_bytes]; /* characters of names */
+char huge* byte_mem_end; /* end of |byte_mem| */
+name_info name_dir[max_names]; /* information about names */
+name_pointer name_dir_end = name_dir+max_names-1;
+@z
+
+
+@x Section 29.
+char *byte_ptr; /* first unused position in |byte_mem| */
+@y
+char huge* byte_ptr; /* first unused position in |byte_mem| */
+@z
+
+
+@x Section 30.
+@ @<Init...@>=
+name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
+name_ptr=name_dir+1; /* |name_dir[0]| will be used only for error recovery */
+name_ptr->byte_start=byte_mem; /* this makes name 0 of length zero */
+@y
+@ @<Init...@>=
+name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
+name_ptr=name_dir+1; /* |name_dir[0]| will be used only for error recovery */
+name_ptr->byte_start=byte_mem; /* this makes name 0 of length zero */
+byte_mem_end = byte_mem+max_bytes-1;
+@z
+
+
+@x Section 42.
+void
+print_section_name(p)
+name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+@y
+void
+print_section_name(p)
+name_pointer p;
+{
+ char huge* ss, huge* s = first_chunk(p);
+@z
+
+
+@x Section 43.
+void
+sprint_section_name(dest,p)
+ char*dest;
+ name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+@y
+void
+sprint_section_name(dest,p)
+ char*dest;
+ name_pointer p;
+{
+ char huge* ss, huge* s = first_chunk(p);
+@z
+
+
+@x Section 44.
+void
+print_prefix_name(p)
+name_pointer p;
+{
+ char *s = first_chunk(p);
+@y
+void
+print_prefix_name(p)
+name_pointer p;
+{
+ char huge* s = first_chunk(p);
+@z
+
+
+@x Section 47.
+name_pointer
+add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
+name_pointer par; /* parent of new node */
+int c; /* right or left? */
+char *first; /* first character of section name */
+char *last; /* last character of section name, plus one */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ name_pointer p=name_ptr; /* new node */
+ char *s=first_chunk(p);
+@y
+name_pointer
+add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
+name_pointer par; /* parent of new node */
+int c; /* right or left? */
+char *first; /* first character of section name */
+char *last; /* last character of section name, plus one */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ name_pointer p=name_ptr; /* new node */
+ char huge* s=first_chunk(p);
+@z
+
+
+@x Section 48.
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p; /* name to be extended */
+char *first; /* beginning of extension text */
+char *last; /* one beyond end of extension text */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ char *s;
+@y
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p; /* name to be extended */
+char *first; /* beginning of extension text */
+char *last; /* one beyond end of extension text */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ char huge* s;
+@z
+
+
+@x Section 54.
+int section_name_cmp(pfirst,len,r)
+char **pfirst; /* pointer to beginning of comparison string */
+int len; /* length of string */
+name_pointer r; /* section name being compared */
+{
+ char *first=*pfirst; /* beginning of comparison string */
+ name_pointer q=r+1; /* access to subsequent chunks */
+ char *ss, *s=first_chunk(r);
+@y
+int section_name_cmp(pfirst,len,r)
+char **pfirst; /* pointer to beginning of comparison string */
+int len; /* length of string */
+name_pointer r; /* section name being compared */
+{
+ char *first=*pfirst; /* beginning of comparison string */
+ name_pointer q=r+1; /* access to subsequent chunks */
+ char huge* ss, huge* s=first_chunk(r);
+@z
+
+
+@x Section 55.
+source files, respectively; here we just declare a common field
+|equiv_or_xref| as a pointer to a |char|.
+
+@<More elements of |name...@>=
+char *equiv_or_xref; /* info corresponding to names */
+@y
+source files, respectively. Here we just declare a common field
+|ptr_union| as a union of pointers to |char|, which happen to have
+different addressing attributes.
+
+@<More elements of |name...@>=
+union {
+ char *equiv_member;
+ char huge* xref_member;
+} ptr_union; /* info corresponding to names */
+@z
+
+
+@x Section 69.
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"NUL"| should be used,
+@z
+
+
+@x Section 70.
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+ else if (*s == ':' || *s == '\\' || *s == '/')
+ dot_pos=NULL,name_pos=++s;
+@z
+
+
+@x Section 70.
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-mac.ch b/Build/source/texk/web2c/cwebdir/comm-mac.ch
new file mode 100644
index 00000000000..b9bd408655e
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-mac.ch
@@ -0,0 +1,150 @@
+This is the change file to CWEB's COMMON for porting to Macintoshes.
+No changes to CTANGLE or CWEAVE are needed.
+
+(Contributed 13 Oct 2000 by AndPio@aol.com; slightly edited by Don Knuth)
+
+@x in limbo, change the title page document to specify Mac version
+ \centerline{(Version 3.64)}
+@y
+ \centerline{(Version 3.64 for MacOS)}
+@z
+
+@x section 9: Make input_ln accept \n, \r, \n\r, or \r\n as line endings
+@ In the unlikely event that your standard I/O library does not
+support |feof|, |getc|, and |ungetc| you may have to change things here.
+@^system dependencies@>
+
+@c
+int input_ln(fp) /* copies a line into |buffer| or returns 0 */
+FILE *fp; /* what file to read from */
+{
+ register int c=EOF; /* character read; initialized so some compilers won't complain */
+ register char *k; /* where next character goes */
+ if (feof(fp)) return(0); /* we have hit end-of-file */
+ limit = k = buffer; /* beginning of buffer */
+ while (k<=buffer_end && (c=getc(fp)) != EOF && c!='\n')
+ if ((*(k++) = c) != ' ') limit = k;
+ if (k>buffer_end)
+ if ((c=getc(fp))!=EOF && c!='\n') {
+ ungetc(c,fp); loc=buffer; err_print("! Input line too long");
+@.Input line too long@>
+ }
+ if (c==EOF && limit==buffer) return(0); /* there was nothing after
+ the last newline */
+ return(1);
+}
+@y
+@ In the unlikely event that your standard I/O library does not
+support |feof|, |getc|, and |ungetc| you may have to change things here.
+
+This |input_ln| function accepts |"\n"|, |"\r"|, |"\n\r"| and |"\r\n"| as
+line endings, so that \.{CWEB} will works with ASCII files stored in
+\UNIX/, {\mc DOS} or {\mc MAC} format.
+@^system dependencies@>
+
+@c
+int input_ln(fp) /* copies a line into |buffer| or returns 0 */
+FILE *fp; /* what file to read from */
+{
+ register int c=EOF; /* character read; initialized so some compilers won't complain */
+ register char *k; /* where next character goes */
+ if (feof(fp)) return(0); /* we have hit end-of-file */
+ limit = k = buffer; /* beginning of buffer */
+ while (1) {
+ c = getc(fp);
+ if (c==EOF) return (limit!=buffer); /* 0, if there was nothing after
+ the last newline */
+ else if (c=='\n' || c=='\r') { /* we have hit end-of-line */
+ int d = getc(fp);
+ if (c+d!='\n'+'\r') /* no combination |"\n\r"| or |"\r\n"| */
+ ungetc(d,fp);
+ return (1);
+ }
+ else if (k>buffer_end) {
+ ungetc(c,fp); loc=buffer; err_print("! Input line too long");
+ return (1);
+@.Input line too long@>
+ }
+ else
+ if ((*(k++)=c) != ' ') limit = k;
+ }
+}
+@z
+
+@x section 12, simply return if no change file was specified
+ change_limit=change_buffer; /* this value is used if the change file ends */
+ @<Skip over comment lines in the change file; |return| if end of file@>;
+@y
+ change_limit=change_buffer; /* this value is used if the change file ends */
+ if (change_file_name[0] == '\0') /* no change file specified */
+ return; /* so we have reached the end of that file */
+ @<Skip over comment lines in the change file; |return| if end of file@>;
+@z
+
+@x section 19, don't try to open a change file if none was specified
+if ((change_file=fopen(change_file_name,"r"))==NULL)
+ fatal("! Cannot open change file ", change_file_name);
+@y
+if (change_file_name[0] == '\0') /* no change file specified */
+ change_file = NULL; /* reset at least the |change_file| */
+else if ((change_file=fopen(change_file_name,"r"))==NULL)
+ fatal("! Cannot open change file ", change_file_name);
+@z
+
+@x section 22, declare colon as Mac's path separator
+(Colon-separated paths are not supported.)
+The remainder of the \.{@@i} line after the file name is ignored.
+
+@y
+(Colon-separated path alternatives in the style of \UNIX/ or Kpathsea
+are not supported. On a Macintosh, colons are used to separate the names on
+different levels of a path.)
+The remainder of the \.{@@i} line after the file name is ignored.
+
+@d PATH_SEP ':' /* MacOS pathname separator */
+@^system dependencies@>
+@z
+
+@x section 23, use the path separator constant
+ cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+@y
+ cur_file_name[l]=PATH_SEP; /* pathname separator */
+@z
+
+@x section 69, explain the convention for omitted change files
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that no change file should be used,
+@z
+
+@x section 70, use the Metrowerks |ccommand| to access command lines
+ while (--argc > 0) {
+@y
+ argc = ccommand (&argv); /* use Mac interface to command line */
+@^system dependencies@>
+ while (--argc > 0) {
+@z
+@x section 70, use the path separator constant
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+ else if (*s==PATH_SEP) dot_pos=NULL,name_pos=++s;
+@z
+@x section 70, make change file name empty when it is unspecified
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) change_file_name[0]='\0'; /* empty string */
+@z
+
+@x section 82, insert an extra module before the index
+@** Index.
+@y by putting the new module here, we preserve all the previous section numbers
+@ We assume an interface to \CEE/ command-line emulation as supplied by
+the |ccommand| function of Metrowerks CodeWarrior, as defined in
+the header file \.{console.h}.
+
+@<Include files@>=
+#include <console.h>
+@^system dependencies@>
+
+@** Index.
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-man.ch b/Build/source/texk/web2c/cwebdir/comm-man.ch
new file mode 100644
index 00000000000..c922c036312
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-man.ch
@@ -0,0 +1,22 @@
+Change file to help make Appendix D of the full CWEB manual
+@x
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+@y
+\def\botofcontents{\vfill\titlefalse}
+\def\contentspagenumber{28}
+\def\title{APPENDIX D: COMMON}
+\let\K=\leftarrow
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-os2.ch b/Build/source/texk/web2c/cwebdir/comm-os2.ch
new file mode 100644
index 00000000000..5e20a6706ce
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-os2.ch
@@ -0,0 +1,24 @@
+This is the change file for CWEB's COMMON under OS/2
+(Contributed by Jim Nutt, jnutt@PrimeNet.Com, May 1995)
+
+These changes tested with WATCOM C v10.0a.
+No changes to CTANGLE or CWEAVE are needed with OS/2.
+
+@x section 69
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"NUL"| should be used,
+@z
+
+@x section 70 (this change copied from comm-pc.ch)
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+ else if (*s == ':' || *s == '\\' || *s == '/')
+ dot_pos=NULL,name_pos=++s;
+@z
+
+@x section 70
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-pc.ch b/Build/source/texk/web2c/cwebdir/comm-pc.ch
new file mode 100644
index 00000000000..e69bafb5244
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-pc.ch
@@ -0,0 +1,33 @@
+This is the change file for CWEB's COMMON under DOS
+(Contributed by Lee Wittenberg, March 1993)
+
+Changes necessary for compiling with Borland C/C++
+Use compilation switches -mc -w-pro -Ff=5000
+
+Note: The change to section 27 is not necessary if using a compiler
+that allows >64K arrays.
+
+@x section 27
+@d max_bytes 90000 /* the number of bytes in identifiers,
+@y
+@d max_bytes (unsigned)60000 /* the number of bytes in identifiers,
+@z
+
+@x section 69
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"NUL"| should be used,
+@z
+
+@x section 70 (this change copied from comm-bs.ch, July 94)
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+ else if (*s == ':' || *s == '\\' || *s == '/')
+ dot_pos=NULL,name_pos=++s;
+@z
+
+@x section 70
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-ql.ch b/Build/source/texk/web2c/cwebdir/comm-ql.ch
new file mode 100644
index 00000000000..8859e215b2a
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-ql.ch
@@ -0,0 +1,332 @@
+This is the change file for CWEB's COMMON under QSOD/SMSQ
+(Contributed by Robert H. Klein, September 1994)
+
+This change file is intended for use with C68 v4.13 (or later).
+compile with
+ex <dev_>cc;'-v -h -c -=500000 -DCWEBINPUTS=flp2_ common_c'
+
+
+
+@x
+\def\v{\char'174} % vertical (|) in typewriter font
+
+\def\title{Common code for CTANGLE and CWEAVE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+@y
+\def\v{\char'174} % vertical (|) in typewriter font
+
+\def\title{Common code for CTANGLE and CWEAVE (QL Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+@z
+
+@x
+The line number of each open file is also kept for error reporting and
+for the benefit of \.{CTANGLE}.
+
+@f line x /* make |line| an unreserved word */
+@d max_include_depth 10 /* maximum number of source files open
+ simultaneously, not counting the change file */
+@d max_file_name_length 60
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+@d web_file file[0] /* main source file */
+@d web_file_name file_name[0] /* main source file name */
+@y
+The line number of each open file is also kept for error reporting and
+for the benefit of \.{CTANGLE}.
+
+For use on QDOS/SMSQ systems the variable |max_file_name_length| is shortened
+to 42 characters, i.e. 5 characters for the device name, 36 characters
+for the file name plus one character as string terminator. (Note that
+(current) QDOS/SMSQ file systems have a limitation of 36 characters as
+maximum length for a file name.
+
+@f line x /* make |line| an unreserved word */
+@d max_include_depth 10 /* maximum number of source files open
+ simultaneously, not counting the change file */
+@d max_file_name_length 42
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+@d web_file file[0] /* main source file */
+@d web_file_name file_name[0] /* main source file name */
+@z
+
+
+@x
+ cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+@y
+ cur_file_name[l]='_'; /* QDOS/SMSQ pathname separator */
+@z
+
+
+@x
+@ We now must look at the command line arguments and set the file names
+accordingly. At least one file name must be present: the \.{CWEB}
+file. It may have an extension, or it may omit the extension to get |".w"| or
+|".web"| added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+file name extension by |".tex"|, and the \CEE/ file name by replacing
+the extension by |".c"|, after removing the directory name (if any).
+
+If there is a second file name present among the arguments, it is the
+change file, again either with an extension or without one to get |".ch"|.
+An omitted change file argument means that |"/dev/null"| should be used,
+when no changes are desired.
+@^system dependencies@>
+
+If there's a third file name, it will be the output file.
+
+@<Pred...@>=
+void scan_args();
+
+@ @c
+void
+scan_args()
+{
+ char *dot_pos; /* position of |'.'| in the argument */
+ char *name_pos; /* file name beginning, sans directory */
+ register char *s; /* register for scanning strings */
+ boolean found_web=0,found_change=0,found_out=0;
+ /* have these names have been seen? */
+ boolean flag_change;
+
+ while (--argc > 0) {
+ if ((**(++argv)=='-'||**argv=='+')&&*(*argv+1)) @<Handle flag argument@>@;
+ else {
+ s=name_pos=*argv;@+dot_pos=NULL;
+ while (*s) {
+ if (*s=='.') dot_pos=s++;
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+ if (!found_web) @<Make
+ |web_file_name|, |tex_file_name| and |C_file_name|@>@;
+ else if (!found_change) @<Make |change_file_name| from |fname|@>@;
+ else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;
+ else @<Print usage error message and quit@>;
+ }
+ }
+ if (!found_web) @<Print usage error message and quit@>;
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+}
+
+@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,
+otherwise we add |".w"|. If this file can't be opened, we prepare an
+|alt_web_file_name| by adding |"web"| after the dot.
+The other file names come from adding other things
+after the dot. We must check that there is enough room in
+|web_file_name| and the other arrays for the argument.
+
+@<Make |web_file_name|...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(web_file_name,"%s.w",*argv);
+ else {
+ strcpy(web_file_name,*argv);
+ *dot_pos=0; /* string now ends where the dot was */
+ }
+ sprintf(alt_web_file_name,"%s.web",*argv);
+ sprintf(tex_file_name,"%s.tex",name_pos); /* strip off directory name */
+ sprintf(idx_file_name,"%s.idx",name_pos);
+ sprintf(scn_file_name,"%s.scn",name_pos);
+ sprintf(C_file_name,"%s.c",name_pos);
+ found_web=1;
+}
+
+@ @<Make |change_file_name|...@>=
+{
+ if (strcmp(*argv,"-")==0) found_change=-1;
+ else {
+ if (s-*argv > max_file_name_length-4)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(change_file_name,"%s.ch",*argv);
+ else strcpy(change_file_name,*argv);
+ found_change=1;
+ }
+}
+
+@ @<Override...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL) {
+ sprintf(tex_file_name,"%s.tex",*argv);
+ sprintf(idx_file_name,"%s.idx",*argv);
+ sprintf(scn_file_name,"%s.scn",*argv);
+ sprintf(C_file_name,"%s.c",*argv);
+ } else {
+ strcpy(tex_file_name,*argv);
+ strcpy(C_file_name,*argv);
+ if (flags['x']) { /* indexes will be generated */
+ *dot_pos=0;
+ sprintf(idx_file_name,"%s.idx",*argv);
+ sprintf(scn_file_name,"%s.scn",*argv);
+ }
+ }
+ found_out=1;
+}
+@y
+@ We now must look at the command line arguments and set the file names
+accordingly. At least one file name must be present: the \.{CWEB}
+file. It may have an extension, or it may omit the extension to get |"_w"| or
+|"_web"| added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+file name extension by |"_tex"|, and the \CEE/ file name by replacing
+the extension by |"_c"|, after removing the directory name (if any).
+
+If there is a second file name present among the arguments, it is the
+change file, again either with an extension or without one to get |"_ch"|.
+An omitted change file argument means that |"NUL"| should be used,
+when no changes are desired.
+@^system dependencies@>
+
+If there's a third file name, it will be the output file.
+
+Because |"_"| is a directory {\em and} extension separator, \.{CWEB} will
+always use the {\em full} name (i.e. with full path). Fortunately the
+routine has been written to search for the last ``dot'', so the altered
+version will search for the last |"_"| (including directory separators),
+so we have what we want.
+
+@<Pred...@>=
+void scan_args();
+
+@ @c
+void
+scan_args()
+{
+ char *dot_pos; /* position of |'_'| in the argument */
+ char *name_pos; /* file name beginning, sans directory */
+ register char *s; /* register for scanning strings */
+ boolean found_web=0,found_change=0,found_out=0;
+ /* have these names have been seen? */
+ boolean flag_change;
+
+ while (--argc > 0) {
+ if ((**(++argv)=='-'||**argv=='+')&&*(*argv+1)) @<Handle flag argument@>@;
+ else {
+ s=name_pos=*argv;@+dot_pos=NULL;
+ while (*s) {
+ if (*s=='_') dot_pos=s++;
+ else if (*s=='_') dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+ if (!found_web) @<Make
+ |web_file_name|, |tex_file_name| and |C_file_name|@>@;
+ else if (!found_change) @<Make |change_file_name| from |fname|@>@;
+ else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;
+ else @<Print usage error message and quit@>;
+ }
+ }
+ if (!found_web) @<Print usage error message and quit@>;
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+}
+
+@ We use all of |*argv| for the |web_file_name| if there is a |'_'| in it,
+otherwise we add |"_w"|. If this file can't be opened, we prepare an
+|alt_web_file_name| by adding |"web"| after the dot.
+The other file names come from adding other things
+after the dot. We must check that there is enough room in
+|web_file_name| and the other arrays for the argument.
+
+If you've read the section before carefully you'll have noticed, that
+QDOS/SMSQ file names contain almost a |"_"|, so this routine will not work,
+i.e. you'll {\em have} to add the |"_w"| always. Nevertheless I adapted
+the routine as if it would work.
+
+@<Make |web_file_name|...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(web_file_name,"%s_w",*argv);
+ else {
+ strcpy(web_file_name,*argv);
+ *dot_pos=0; /* string now ends where the dot was */
+ }
+ sprintf(alt_web_file_name,"%s_web",*argv);
+ sprintf(tex_file_name,"%s_tex",name_pos); /* strip off directory name */
+ sprintf(idx_file_name,"%s_idx",name_pos);
+ sprintf(scn_file_name,"%s_scn",name_pos);
+ sprintf(C_file_name,"%s_c",name_pos);
+ found_web=1;
+}
+
+@ @<Make |change_file_name|...@>=
+{
+ if (strcmp(*argv,"-")==0) found_change=-1;
+ else {
+ if (s-*argv > max_file_name_length-4)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(change_file_name,"%s_ch",*argv);
+ else strcpy(change_file_name,*argv);
+ found_change=1;
+ }
+}
+
+@ @<Override...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL) {
+ sprintf(tex_file_name,"%s_tex",*argv);
+ sprintf(idx_file_name,"%s_idx",*argv);
+ sprintf(scn_file_name,"%s_scn",*argv);
+ sprintf(C_file_name,"%s_c",*argv);
+ } else {
+ strcpy(tex_file_name,*argv);
+ strcpy(C_file_name,*argv);
+ if (flags['x']) { /* indexes will be generated */
+ *dot_pos=0;
+ sprintf(idx_file_name,"%s_idx",*argv);
+ sprintf(scn_file_name,"%s_scn",*argv);
+ }
+ }
+ found_out=1;
+}
+@z
+
+
+@x
+@ @<Print usage error message and quit@>=
+{
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+}
+@y
+@ @<Print usage error message and quit@>=
+{
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[_w] [{changefile[_ch]|-} [outfile[_c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[_w] [{changefile[_ch]|-} [outfile[_tex]]]\n"
+ ,"");
+}
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-vms.ch b/Build/source/texk/web2c/cwebdir/comm-vms.ch
new file mode 100644
index 00000000000..cd5fe524393
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-vms.ch
@@ -0,0 +1,81 @@
+This is the change file for CWEB's COMMON under VAX/VMS.
+
+created:
+ 1987 BL (Bjorn Larsen, University of Oslo)
+
+modified:
+ 01-FEB-1992 ST (Stephan Trebels <trebels@ams02.dnet.gwdg.de>)
+ > include ctype,stdio,ssdef from textlibrary SYS$SHARE:VAXCDEF.TLB
+ > change error return code to SS$_ABORT
+ (perhaps better than %NONAME-E-NOMSG, Message number 2 )
+
+(also modified by Don Knuth to match changes in the master file)
+(only the two changes by BL are necessary for initial bootstrapping
+ via hand-editing of common.c)
+
+@x section 5 (01-FEB-1992 ST)
+#include <ctype.h>
+@y
+#include ctype /* VMS searches Textlibraries faster */
+@z
+
+@x section 8 (01-FEB-1992 ST)
+#include <stdio.h>
+@y
+#include stdio /* VMS searches Textlibraries faster */
+@z
+
+@x section 61 (01-FEB-1992 ST)
+programs are started. Here, for instance, we pass the operating system
+a status of 0 if and only if only harmless messages were printed.
+@y
+programs are started. Here, for instance, we pass VAX/VMS
+a status of |SS$_NORMAL| if and only if only harmless
+messages have been printed.
+A suitable status to signal an error condition to VAX/VMS could be
+|SS$_ABORT|, telling the operating system to
+print |"%SYSTEM-F-ABORT, abort"|, if |history > harmless_message|.
+@z
+
+@x section 61 (1987 BL) (01-FEB-1992 ST) (11-JAN-1993 DEK)
+ if (history > harmless_message) return(1);
+ else return(0);
+@y
+/*
+ VAX/VMS and UNIX have different error status conventions.
+ VAX/VMS uses odd values (for example |SS$_NORMAL|) to indicate success,
+ even values indicate errors, resulting in messages displayed
+ on the screen. |SS$_ABORT| has been chosen, to indicate an
+ error and display something that's not complete nonsense.
+*/
+ if (history > harmless_message) exit(SS$_ABORT);
+ else exit(SS$_NORMAL);
+@z
+
+@x section 69 (01-FEB-1992 ST)
+An omitted change file argument means that |"/dev/null"| should be used,
+when no changes are desired.
+@y
+An omitted change file argument means that the
+null device |"NL:"| should be used, when no changes are desired.
+@z
+
+@x section 70 (1987 BL) (01-FEB-1992 ST) (05-APR-1992 DEK)
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=) strcpy(change_file_name,"NL:");
+ /* {\tt NL:} is the VAX/VMS notation for {\tt /dev/null} */
+@z
+
+@x section 82 (01-FEB-1992 ST)
+@** Index.
+@y
+@* VAX/VMS specific code.
+We have used |SS$_NORMAL| and |SS$_ABORT| as return codes,
+so we have to include the system message codes.
+
+@<Include files@>=
+#include ssdef /* we need VAX/VMS system messages */
+
+@** Index.
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-w2c.ch b/Build/source/texk/web2c/cwebdir/comm-w2c.ch
new file mode 100644
index 00000000000..2a80aca53c6
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-w2c.ch
@@ -0,0 +1,620 @@
+% Kpathsea changes for CWEB by Wlodek Bzyl and Olaf Weber
+% Copyright 2002 Wlodek Bzyl and Olaf Weber
+% This file is in the Public Domain.
+
+@x l.20
+\def\title{Common code for CTANGLE and CWEAVE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+@y
+\def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}}
+\def\title{Common code for CTANGLE and CWEAVE (Version 3.64k)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.64k)}
+ \vfill}
+@z
+
+This change can not be applied when `tie' is used
+(TOC file can not be typeset).
+
+%@x l.42
+%\let\maybe=\iftrue
+%@y
+%\let\maybe=\iffalse % print only changed modules
+%@z
+
+
+Section 2.
+We use the definition from `kpathsea/types.h':
+
+ typedef enum { false = 0, true = 1 } boolean;
+
+Note that this definition also occurs in common.h.
+@x l.74
+typedef short boolean;
+@y
+@z
+
+
+Section 4.
+
+@x l.91
+common_init()
+@y
+common_init P1H(void)
+@z
+
+@x l.93
+ @<Initialize pointers@>;
+@y
+ @<Initialize pointers@>;
+ @<Set up |PROGNAME| feature and initialize the search path mechanism@>;
+@z
+
+Section 9.
+
+@x l.173
+int input_ln(fp) /* copies a line into |buffer| or returns 0 */
+FILE *fp; /* what file to read from */
+@y
+int input_ln P1C(FILE *, fp) /* copies a line into |buffer| or returns 0 */
+@z
+
+Section 10.
+
+@x l.207 - max_file_name_length is way too small.
+@d max_file_name_length 60
+@y
+@d max_file_name_length 1024
+@z
+
+@x l.221 - no alt_web_file_name needed.
+char alt_web_file_name[max_file_name_length]; /* alternate name to try */
+@y
+@z
+
+Section 12.
+
+@x l.254
+prime_the_change_buffer()
+@y
+prime_the_change_buffer P1H(void)
+@z
+
+Section 16.
+
+@x l.322
+check_change() /* switches to |change_file| if the buffers match */
+@y
+check_change P1H(void) /* switches to |change_file| if the buffers match */
+@z
+
+Section 18.
+
+@x l.380
+reset_input()
+@y
+reset_input P1H(void)
+@z
+
+Section 19.
+
+@x l.394
+if ((web_file=fopen(web_file_name,"r"))==NULL) {
+ strcpy(web_file_name,alt_web_file_name);
+ if ((web_file=fopen(web_file_name,"r"))==NULL)
+ fatal("! Cannot open input file ", web_file_name);
+}
+@y
+if ((found_filename=kpse_find_cweb(web_file_name))==NULL ||
+ (web_file=fopen(found_filename,"r"))==NULL) {
+ fatal("! Cannot open input file ", web_file_name);
+} else if (strlen(found_filename) < max_file_name_length) {
+ strcpy(web_file_name, found_filename);
+ free(found_filename);
+}
+@z
+
+@x l.402
+if ((change_file=fopen(change_file_name,"r"))==NULL)
+ fatal("! Cannot open change file ", change_file_name);
+@y
+if ((found_filename=kpse_find_cweb(change_file_name))==NULL ||
+ (change_file=fopen(found_filename,"r"))==NULL) {
+ fatal("! Cannot open change file ", change_file_name);
+} else if (strlen(found_filename) < max_file_name_length) {
+ strcpy(change_file_name, found_filename);
+ free(found_filename);
+}
+@z
+
+Section 21.
+
+@x l.427
+int get_line() /* inputs the next line */
+@y
+int get_line P1H(void) /* inputs the next line */
+@z
+
+Section 22.
+
+@x l.472
+#include <stdlib.h> /* declaration of |getenv| and |exit| */
+@y
+#include <stdlib.h> /* declaration of |getenv| and |exit| */
+#define CWEB
+#include "cpascal.h"
+#include <kpathsea/kpathsea.h> /* include every \Kpathsea/ header */
+#include "help.h"
+
+@ The \.{ctangle} and \.{cweave} programs from the original \.{CWEB}
+package use the compile-time default directory or the value of the
+environment variable \.{CWEBINPUTS} as an alternative place to be
+searched for files, if they could not be found in the current
+directory.
+
+This version uses the \Kpathsea/ mechanism for searching files.
+The directories to be searched for come from three sources:
+
+ (a)~a user-set environment variable \.{CWEBINPUTS}
+ (overriden by \.{CWEBINPUTS\_cweb});\par
+ (b)~a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break
+ e.g. \.{CWEBINPUTS=.:$TEXMF/texmf/cweb//}
+ or \.{CWEBINPUTS.cweb=.:$TEXMF/texmf/cweb//};\hangindent=2\parindent\par
+ (c)~compile-time default directories \.{.:$TEXMF/texmf/cweb//}
+ (specified in \.{texmf.in}).
+
+
+@d kpse_find_cweb(name) kpse_find_file(name,kpse_cweb_format,true)
+
+@ The simple file searching is replaced by `path searching' mechanism
+that \Kpathsea/ library provides.
+
+We set |kpse_program_name| to a |"cweb"|. This means if the
+variable |CWEBINPUTS.cweb| is present in \.{texmf.cnf} (or |CWEBINPUTS_cweb|
+in the environment) its value will be used as the search path for
+filenames. This allows different flawors of \.{CWEB} to have
+different search paths.
+
+FIXME: Not sure this is the best way to go about this.
+
+@<Set up |PROGNAME| feature and initialize the search path mechanism@>=
+kpse_set_program_name(argv[0], "cweb");
+@z
+
+
+Section 23.
+
+@x l.475
+ char temp_file_name[max_file_name_length];
+ char *cur_file_name_end=cur_file_name+max_file_name_length-1;
+ char *k=cur_file_name, *kk;
+ int l; /* length of file name */
+@y
+ char *cur_file_name_end=cur_file_name+max_file_name_length-1;
+ char *k=cur_file_name;
+@z
+
+@x l.489
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+@y
+ if ((found_filename=kpse_find_cweb(cur_file_name))!=NULL &&
+ (cur_file=fopen(found_filename,"r"))!=NULL) {
+ /* Copy name for #line directives. */
+ if (strlen(found_filename) < max_file_name_length) {
+ strcpy(cur_file_name, found_filename);
+ free(found_filename);
+ }
+@z
+
+Replaced by Kpathsea `kpse_find_file'
+
+@x l.493
+ kk=getenv("CWEBINPUTS");
+ if (kk!=NULL) {
+ if ((l=strlen(kk))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,kk);
+ }
+ else {
+#ifdef CWEBINPUTS
+ if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,CWEBINPUTS);
+#else
+ l=0;
+#endif /* |CWEBINPUTS| */
+ }
+ if (l>0) {
+ if (k+l+2>=cur_file_name_end) too_long();
+@.Include file name ...@>
+ for (; k>= cur_file_name; k--) *(k+l+1)=*k;
+ strcpy(cur_file_name,temp_file_name);
+ cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+ cur_line=0; print_where=1;
+ goto restart; /* success */
+ }
+ }
+@y
+@z
+
+Section 26.
+
+@x l.571
+check_complete(){
+@y
+check_complete P1H(void) {
+@z
+
+Section 33.
+
+@x l.651
+extern int names_match();
+@y
+extern int names_match P4H(name_pointer, char*, int, char);
+@z
+
+Section 35.
+
+@x l.661
+id_lookup(first,last,t) /* looks up a string in the identifier table */
+char *first; /* first character of string */
+char *last; /* last character of string plus one */
+char t; /* the |ilk|; used by \.{CWEAVE} only */
+@y
+/* looks up a string in the identifier table */
+id_lookup P3C(char*,first, char*,last, char,t)
+@z
+
+Section 38.
+
+@x l.704
+void init_p();
+@y
+extern void init_p P2C(name_pointer,p, char,t);
+@z
+
+Section 42.
+
+@x l.766
+print_section_name(p)
+name_pointer p;
+@y
+print_section_name P1C(name_pointer, p)
+@z
+
+Section 43.
+
+@x l.785
+sprint_section_name(dest,p)
+ char*dest;
+ name_pointer p;
+@y
+sprint_section_name P2C(char*,dest, name_pointer,p)
+@z
+
+Section 44.
+
+@x l.806
+print_prefix_name(p)
+name_pointer p;
+@y
+print_prefix_name P1C(name_pointer,p)
+@z
+
+Section 45.
+
+@x l.826
+int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */
+ char *j, *k; /* beginning of first and second strings */
+ int j_len, k_len; /* length of strings */
+@y
+/* fuller comparison than |strcmp| */
+int web_strcmp P4C(char*,j, int,j_len, char*,k, int,k_len)
+@z
+
+Section 46.
+
+@x l.853
+extern void init_node();
+@y
+extern void init_node P1C(name_pointer,node);
+@z
+
+Section 47.
+
+@x l.857
+add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
+name_pointer par; /* parent of new node */
+int c; /* right or left? */
+char *first; /* first character of section name */
+char *last; /* last character of section name, plus one */
+int ispref; /* are we adding a prefix or a full name? */
+@y
+/* install a new node in the tree */
+add_section_name P5C(name_pointer,par, int,c, char*,first, char*,last,
+ int,ispref)
+@z
+
+Section 48.
+
+@x l.886
+extend_section_name(p,first,last,ispref)
+name_pointer p; /* name to be extended */
+char *first; /* beginning of extension text */
+char *last; /* one beyond end of extension text */
+int ispref; /* are we adding a prefix or a full name? */
+@y
+extend_section_name P4C(name_pointer,p, char*,first, char*,last, int,ispref)
+@z
+
+Section 49.
+
+@x l.914
+section_lookup(first,last,ispref) /* find or install section name in tree */
+char *first, *last; /* first and last characters of new name */
+int ispref; /* is the new name a prefix or a full name? */
+@y
+/* find or install section name in tree */
+section_lookup P3C(char*,first, char*,last, int,ispref)
+@z
+
+Section 53.
+
+@x l.1018
+int section_name_cmp();
+@y
+int section_name_cmp P3H(char**, int, name_pointer);
+@z
+
+Section 54.
+
+@x l.1021
+int section_name_cmp(pfirst,len,r)
+char **pfirst; /* pointer to beginning of comparison string */
+int len; /* length of string */
+name_pointer r; /* section name being compared */
+@y
+int section_name_cmp P3C(char**,pfirst, int,len, name_pointer,r)
+@z
+
+Section 57.
+
+@x l.1093
+void err_print();
+@y
+void err_print P1H(char*);
+@z
+
+Section 58.
+
+@x l.1098
+err_print(s) /* prints `\..' and location of error message */
+char *s;
+@y
+err_print P1C(char*,s) /* prints `\..' and location of error message */
+@z
+
+Section 60.
+
+@x l.1141
+int wrap_up();
+extern void print_stats();
+@y
+int wrap_up P1H(void);
+extern void print_stats P1H(void);
+@z
+
+Section 61.
+
+@x l.1151
+int wrap_up() {
+@y
+int wrap_up P1H(void) {
+@z
+
+Section 63.
+
+@x l.1174
+void fatal(), overflow();
+@y
+void fatal P2H(char*,char*);
+void overflow(char*);
+@z
+
+Section 64.
+
+@x l.1180
+fatal(s,t)
+ char *s,*t;
+@y
+fatal P2C(char*,s, char*,t)
+@z
+
+Section 65.
+
+@x l.1191
+overflow(t)
+ char *t;
+@y
+overflow P1C(char*,t)
+@z
+
+Section 67.
+
+@x l.1212
+the names of those files. Most of the 128 flags are undefined but available
+for future extensions.
+@y
+the names of those files. Most of the 128 flags are undefined but available
+for future extensions.
+
+We use `kpathsea' library functions to find literate sources and
+NLS configuration files. When the files you expect are not
+being found, the thing to do is to enable `kpathsea' runtime
+debugging by assigning to |kpathsea_debug| variable a small number
+via `\.{-d}' option. The meaning of number is shown below. To set
+more than one debugging options sum the corresponding numbers.
+$$\halign{\hskip5em\tt\hfil#&&\qquad\tt#\cr
+ 1&report `\.{stat}' calls\cr
+ 2&report lookups in all hash tables\cr
+ 4&report file openings and closings\cr
+ 8&report path information\cr
+16&report directory list\cr
+32&report on each file search\cr
+64&report values of variables being looked up\cr}$$
+Debugging output is always written to |stderr|, and begins with the string
+`\.{kdebug:}'.
+@z
+
+@x l.1218
+@d show_happiness flags['h'] /* should lack of errors be announced? */
+@y
+@d show_happiness flags['h'] /* should lack of errors be announced? */
+@d show_kpathsea_debug flags['d']
+ /* should results of file searching be shown? */
+@z
+
+@x l.1234
+show_banner=show_happiness=show_progress=1;
+@y
+show_banner=show_happiness=show_progress=1;
+@z
+
+Section 69.
+
+@x l.1252
+void scan_args();
+@y
+void scan_args P1H(void);
+@z
+
+
+Section 70.
+
+@x l.1257
+scan_args()
+@y
+scan_args P1H(void)
+@z
+
+
+Section 71.
+
+@x l.1282 - use a define for /dev/null
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,DEV_NULL);
+@z
+
+@x l.1302 - no alt_web_file_name
+ sprintf(alt_web_file_name,"%s.web",*argv);
+@y
+@z
+
+
+Section 74.
+
+@x l.1344
+@ @<Handle flag...@>=
+{
+@y
+@ @<Handle flag...@>=
+{
+ if (strcmp("-help",*argv)==0 || strcmp("--help",*argv)==0)
+ @<Display help message and exit@>;
+ if (strcmp("-version",*argv)==0 || strcmp("--version",*argv)==0)
+ @<Display version information and exit@>;
+@z
+
+@x l.1347
+ else flag_change=1;
+@y
+ else flag_change=1;
+ if (*(*argv+1)=='d')
+ if (sscanf(*argv+2,"%u",&kpathsea_debug)!=1) @<Print usage error...@>;
+@z
+
+@x l.1349
+ flags[*dot_pos]=flag_change;
+@y
+ flags[(unsigned char)*dot_pos]=flag_change;
+@z
+
+Section 75.
+
+@x l.1354
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+@y
+if (program==ctangle) {
+ fprintf(stderr, "ctangle: Need one to three file arguments.\n");
+ usage("ctangle");
+} else {
+ fprintf(stderr, "cweave: Need one to three file arguments.\n");
+ usage("cweave");
+}
+@z
+
+Section 77.
+
+@x l.1375
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+@y
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+char *found_filename; /* filename found by |kpse_find_file| */
+@z
+
+
+Section 81. (removed)
+
+@x l.1403
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
+
+@x
+@** Index.
+@y
+@** System dependent changes.
+
+@ Modules for dealing with help messages and version info.
+
+@<Display help message and exit@>=
+usagehelp(program==ctangle ? CTANGLEHELP : CWEAVEHELP, NULL);
+@.--help@>
+
+@ Will have to change these if the version numbers change (ouch).
+
+@d ctangle_banner "This is CTANGLE, Version 3.64"
+@d cweave_banner "This is CWEAVE, Version 3.64"
+
+@<Display version information and exit@>=
+printversionandexit((program==ctangle ? ctangle_banner : cweave_banner),
+ "Silvio Levy and Donald E. Knuth", NULL);
+@.--version@>
+
+@** Index.
+@z
diff --git a/Build/source/texk/web2c/cwebdir/comm-w32.ch b/Build/source/texk/web2c/cwebdir/comm-w32.ch
new file mode 100644
index 00000000000..b300f496d2b
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/comm-w32.ch
@@ -0,0 +1,94 @@
+This is the change file for CWEB's COMMON under Win32
+(Contributed by Fabrice Popineau, February 2002 <Fabrice.Popineau@supelec.fr>)
+
+The Microsoft C compiler included in Visual Studio allows for different
+parameter passing conventions than the standard one. This is actually
+specified with the Intel IA32 architecture. There exist three
+calling conventions under the IA32 architecture as defined by Intel.
+
+One of them is the standard C calling convention: Parameters are passed on
+the stack, calling function is responsible to unstack arguments. Names are
+decorated with a prefixed underscore. It is called the __cdecl convention.
+
+Another calling convention is the __fastcall convention. The first two 32bits
+arguments are passed on the stack. The called function is responsible for
+stack maintenance. Names are decorated with an @ sign as prefix, and another
+@ sign followed by the size of the arguments as suffix.
+
+The third one is the __stdcall convention and is basically the Pascal calling
+convention.
+
+Using the __fastcall convention is usually faster on Intel architecture. Names
+are decorated because obviously a __cdecl function can't behave the same way
+as a __fastcall one of the same prototype. So the new full prototype includes
+the keyword __cdecl or __fastcall. A compiler option allows to compile all
+functions using one or the other calling convention. If you compile using
+__fastcall, then you are bound to explicitly declare a few functions as
+__cdecl : the ones that are passed to the C library (like function pointers
+for qsort() or signal()) or functions that replace functions from the C
+library, because the standard headers have a __cdecl prototype for these
+functions. Also, you cannot declare a library function without giving it the
+exact prototype used in the library headers files. So you'd better use the
+header files to be safe.
+
+Admittedly, this is not vital for cweb, except that I build the whole texlive
+set of programs using the __fastcall convention.
+
+@x
+@<Include files@>=
+#include <ctype.h>
+@y
+@<Include files@>=
+#include <ctype.h>
+#include <string.h>
+@z
+
+@x
+@ @<Predec...@>=
+extern int names_match();
+@y
+@ @<Predec...@>=
+extern int __cdecl names_match();
+@z
+
+@x
+@<Pred...@>=
+void init_p();
+@y
+@<Pred...@>=
+void __cdecl init_p();
+@z
+
+@x section 69
+An omitted change file argument means that |"/dev/null"| should be used,
+@y
+An omitted change file argument means that |"NUL"| should be used,
+@z
+
+@x section 70 (this change copied from comm-bs.ch, July 94)
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+@y
+ else if (*s == ':' || *s == '\\' || *s == '/')
+ dot_pos=NULL,name_pos=++s;
+@z
+
+@x section 70
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+@y
+ if (found_change<=0) strcpy(change_file_name,"NUL");
+@z
+
+@x
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
diff --git a/Build/source/texk/web2c/cwebdir/common.c b/Build/source/texk/web2c/cwebdir/common.c
new file mode 100644
index 00000000000..8fca7c63335
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/common.c
@@ -0,0 +1,1242 @@
+/*1:*/
+#line 58 "common.w"
+
+/*5:*/
+#line 102 "common.w"
+
+#include <ctype.h>
+
+/*:5*//*8:*/
+#line 165 "common.w"
+
+#include <stdio.h>
+
+/*:8*//*22:*/
+#line 471 "common.w"
+
+#include <stdlib.h>
+
+/*:22*/
+#line 59 "common.w"
+
+#define ctangle 0
+#define cweave 1 \
+
+#define and_and 04
+#define lt_lt 020
+#define gt_gt 021
+#define plus_plus 013
+#define minus_minus 01
+#define minus_gt 031
+#define not_eq 032
+#define lt_eq 034
+#define gt_eq 035
+#define eq_eq 036
+#define or_or 037
+#define dot_dot_dot 016
+#define colon_colon 06
+#define period_ast 026
+#define minus_gt_ast 027 \
+
+#define buf_size 100
+#define longest_name 1000
+#define long_buf_size (buf_size+longest_name)
+#define xisspace(c) (isspace(c) &&((unsigned char) c<0200) )
+#define xisupper(c) (isupper(c) &&((unsigned char) c<0200) ) \
+
+#define max_include_depth 10 \
+
+#define max_file_name_length 60
+#define cur_file file[include_depth]
+#define cur_file_name file_name[include_depth]
+#define cur_line line[include_depth]
+#define web_file file[0]
+#define web_file_name file_name[0] \
+
+#define lines_dont_match (change_limit-change_buffer!=limit-buffer|| \
+strncmp(buffer,change_buffer,limit-buffer) ) \
+
+#define if_section_start_make_pending(b) {*limit= '!'; \
+for(loc= buffer;xisspace(*loc) ;loc++) ; \
+*limit= ' '; \
+if(*loc=='@'&&(xisspace(*(loc+1) ) ||*(loc+1) =='*') ) change_pending= b; \
+} \
+
+#define max_sections 2000 \
+ \
+
+#define too_long() {include_depth--; \
+err_print("! Include file name too long") ;goto restart;} \
+
+#define max_bytes 90000 \
+
+#define max_names 4000 \
+ \
+
+#define length(c) (c+1) ->byte_start-(c) ->byte_start
+#define print_id(c) term_write((c) ->byte_start,length((c) ) ) \
+
+#define hash_size 353 \
+
+#define llink link
+#define rlink dummy.Rlink
+#define root name_dir->rlink \
+ \
+
+#define first_chunk(p) ((p) ->byte_start+2)
+#define prefix_length(p) (int) ((unsigned char) *((p) ->byte_start) *256+ \
+(unsigned char) *((p) ->byte_start+1) )
+#define set_prefix_length(p,m) (*((p) ->byte_start) = (m) /256, \
+*((p) ->byte_start+1) = (m) %256) \
+
+#define less 0
+#define equal 1
+#define greater 2
+#define prefix 3
+#define extension 4 \
+
+#define bad_extension 5 \
+
+#define spotless 0
+#define harmless_message 1
+#define error_message 2
+#define fatal_message 3
+#define mark_harmless {if(history==spotless) history= harmless_message;}
+#define mark_error history= error_message \
+
+#define confusion(s) fatal("! This can't happen: ",s) \
+ \
+
+#define show_banner flags['b']
+#define show_progress flags['p']
+#define show_stats flags['s']
+#define show_happiness flags['h'] \
+
+#define update_terminal fflush(stdout) \
+
+#define new_line putchar('\n')
+#define putxchar putchar
+#define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout)
+#define C_printf(c,a) fprintf(C_file,c,a)
+#define C_putc(c) putc(c,C_file) \
+
+
+#line 60 "common.w"
+
+/*2:*/
+#line 73 "common.w"
+
+typedef short boolean;
+boolean program;
+
+/*:2*//*7:*/
+#line 159 "common.w"
+
+char buffer[long_buf_size];
+char*buffer_end= buffer+buf_size-2;
+char*limit= buffer;
+char*loc= buffer;
+
+/*:7*//*10:*/
+#line 214 "common.w"
+
+int include_depth;
+FILE*file[max_include_depth];
+FILE*change_file;
+char file_name[max_include_depth][max_file_name_length];
+
+char change_file_name[max_file_name_length];
+char alt_web_file_name[max_file_name_length];
+int line[max_include_depth];
+int change_line;
+int change_depth;
+boolean input_has_ended;
+boolean changing;
+boolean web_file_open= 0;
+
+/*:10*//*20:*/
+#line 418 "common.w"
+
+typedef unsigned short sixteen_bits;
+sixteen_bits section_count;
+boolean changed_section[max_sections];
+boolean change_pending;
+
+boolean print_where= 0;
+
+/*:20*//*27:*/
+#line 594 "common.w"
+
+typedef struct name_info{
+char*byte_start;
+/*31:*/
+#line 631 "common.w"
+
+struct name_info*link;
+
+/*:31*//*40:*/
+#line 730 "common.w"
+
+union{
+struct name_info*Rlink;
+
+char Ilk;
+}dummy;
+
+/*:40*//*55:*/
+#line 1062 "common.w"
+
+char*equiv_or_xref;
+
+/*:55*/
+#line 597 "common.w"
+
+}name_info;
+typedef name_info*name_pointer;
+char byte_mem[max_bytes];
+char*byte_mem_end= byte_mem+max_bytes-1;
+name_info name_dir[max_names];
+name_pointer name_dir_end= name_dir+max_names-1;
+
+/*:27*//*29:*/
+#line 617 "common.w"
+
+name_pointer name_ptr;
+char*byte_ptr;
+
+/*:29*//*32:*/
+#line 644 "common.w"
+
+typedef name_pointer*hash_pointer;
+name_pointer hash[hash_size];
+hash_pointer hash_end= hash+hash_size-1;
+hash_pointer h;
+
+/*:32*//*56:*/
+#line 1082 "common.w"
+
+int history= spotless;
+
+/*:56*//*67:*/
+#line 1220 "common.w"
+
+int argc;
+char**argv;
+char C_file_name[max_file_name_length];
+char tex_file_name[max_file_name_length];
+char idx_file_name[max_file_name_length];
+char scn_file_name[max_file_name_length];
+boolean flags[128];
+
+/*:67*//*77:*/
+#line 1370 "common.w"
+
+FILE*C_file;
+FILE*tex_file;
+FILE*idx_file;
+FILE*scn_file;
+FILE*active_file;
+
+/*:77*/
+#line 61 "common.w"
+
+/*3:*/
+#line 83 "common.w"
+int phase;
+
+/*:3*//*11:*/
+#line 240 "common.w"
+
+char change_buffer[buf_size];
+char*change_limit;
+
+/*:11*/
+#line 62 "common.w"
+
+/*33:*/
+#line 650 "common.w"
+
+extern int names_match();
+
+/*:33*//*38:*/
+#line 703 "common.w"
+
+void init_p();
+
+/*:38*//*46:*/
+#line 852 "common.w"
+
+extern void init_node();
+
+/*:46*//*53:*/
+#line 1017 "common.w"
+
+int section_name_cmp();
+
+/*:53*//*57:*/
+#line 1092 "common.w"
+
+void err_print();
+
+/*:57*//*60:*/
+#line 1140 "common.w"
+
+int wrap_up();
+extern void print_stats();
+
+/*:60*//*63:*/
+#line 1173 "common.w"
+
+void fatal(),overflow();
+
+/*:63*//*69:*/
+#line 1251 "common.w"
+
+void scan_args();
+
+/*:69*//*81:*/
+#line 1411 "common.w"
+
+extern int strlen();
+extern int strcmp();
+extern char*strcpy();
+extern int strncmp();
+extern char*strncpy();
+
+/*:81*/
+#line 63 "common.w"
+
+
+/*:1*//*4:*/
+#line 89 "common.w"
+
+void
+common_init()
+{
+/*30:*/
+#line 621 "common.w"
+
+name_dir->byte_start= byte_ptr= byte_mem;
+name_ptr= name_dir+1;
+name_ptr->byte_start= byte_mem;
+
+/*:30*//*34:*/
+#line 655 "common.w"
+
+for(h= hash;h<=hash_end;*h++= NULL);
+
+/*:34*//*41:*/
+#line 737 "common.w"
+
+root= NULL;
+
+/*:41*/
+#line 93 "common.w"
+;
+/*68:*/
+#line 1233 "common.w"
+
+show_banner= show_happiness= show_progress= 1;
+
+/*:68*/
+#line 94 "common.w"
+;
+/*78:*/
+#line 1377 "common.w"
+
+scan_args();
+if(program==ctangle){
+if((C_file= fopen(C_file_name,"w"))==NULL)
+fatal("! Cannot open output file ",C_file_name);
+
+}
+else{
+if((tex_file= fopen(tex_file_name,"w"))==NULL)
+fatal("! Cannot open output file ",tex_file_name);
+}
+
+/*:78*/
+#line 95 "common.w"
+;
+}
+
+/*:4*//*9:*/
+#line 172 "common.w"
+
+int input_ln(fp)
+FILE*fp;
+{
+register int c= EOF;
+register char*k;
+if(feof(fp))return(0);
+limit= k= buffer;
+while(k<=buffer_end&&(c= getc(fp))!=EOF&&c!='\n')
+if((*(k++)= c)!=' ')limit= k;
+if(k> buffer_end)
+if((c= getc(fp))!=EOF&&c!='\n'){
+ungetc(c,fp);loc= buffer;err_print("! Input line too long");
+
+}
+if(c==EOF&&limit==buffer)return(0);
+
+return(1);
+}
+
+/*:9*//*12:*/
+#line 251 "common.w"
+
+void
+prime_the_change_buffer()
+{
+change_limit= change_buffer;
+/*13:*/
+#line 265 "common.w"
+
+while(1){
+change_line++;
+if(!input_ln(change_file))return;
+if(limit<buffer+2)continue;
+if(buffer[0]!='@')continue;
+if(xisupper(buffer[1]))buffer[1]= tolower(buffer[1]);
+if(buffer[1]=='x')break;
+if(buffer[1]=='y'||buffer[1]=='z'||buffer[1]=='i'){
+loc= buffer+2;
+err_print("! Missing @x in change file");
+
+}
+}
+
+/*:13*/
+#line 256 "common.w"
+;
+/*14:*/
+#line 282 "common.w"
+
+do{
+change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended after @x");
+
+return;
+}
+}while(limit==buffer);
+
+/*:14*/
+#line 257 "common.w"
+;
+/*15:*/
+#line 292 "common.w"
+
+{
+change_limit= change_buffer+(limit-buffer);
+strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+/*:15*/
+#line 258 "common.w"
+;
+}
+
+/*:12*//*16:*/
+#line 320 "common.w"
+
+void
+check_change()
+{
+int n= 0;
+if(lines_dont_match)return;
+change_pending= 0;
+if(!changed_section[section_count]){
+if_section_start_make_pending(1);
+if(!change_pending)changed_section[section_count]= 1;
+}
+while(1){
+changing= 1;print_where= 1;change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended before @y");
+
+change_limit= change_buffer;changing= 0;
+return;
+}
+if(limit> buffer+1&&buffer[0]=='@'){
+char xyz_code= xisupper(buffer[1])?tolower(buffer[1]):buffer[1];
+/*17:*/
+#line 358 "common.w"
+
+if(xyz_code=='x'||xyz_code=='z'){
+loc= buffer+2;err_print("! Where is the matching @y?");
+
+}
+else if(xyz_code=='y'){
+if(n> 0){
+loc= buffer+2;
+printf("\n! Hmm... %d ",n);
+err_print("of the preceding lines failed to match");
+
+}
+change_depth= include_depth;
+return;
+}
+
+/*:17*/
+#line 342 "common.w"
+;
+}
+/*15:*/
+#line 292 "common.w"
+
+{
+change_limit= change_buffer+(limit-buffer);
+strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+/*:15*/
+#line 344 "common.w"
+;
+changing= 0;cur_line++;
+while(!input_ln(cur_file)){
+if(include_depth==0){
+err_print("! CWEB file ended during a change");
+
+input_has_ended= 1;return;
+}
+include_depth--;cur_line++;
+}
+if(lines_dont_match)n++;
+}
+}
+
+/*:16*//*18:*/
+#line 378 "common.w"
+
+void
+reset_input()
+{
+limit= buffer;loc= buffer+1;buffer[0]= ' ';
+/*19:*/
+#line 393 "common.w"
+
+if((web_file= fopen(web_file_name,"r"))==NULL){
+strcpy(web_file_name,alt_web_file_name);
+if((web_file= fopen(web_file_name,"r"))==NULL)
+fatal("! Cannot open input file ",web_file_name);
+}
+
+
+web_file_open= 1;
+if((change_file= fopen(change_file_name,"r"))==NULL)
+fatal("! Cannot open change file ",change_file_name);
+
+/*:19*/
+#line 383 "common.w"
+;
+include_depth= 0;cur_line= 0;change_line= 0;
+change_depth= include_depth;
+changing= 1;prime_the_change_buffer();changing= !changing;
+limit= buffer;loc= buffer+1;buffer[0]= ' ';input_has_ended= 0;
+}
+
+/*:18*//*21:*/
+#line 426 "common.w"
+
+int get_line()
+{
+restart:
+if(changing&&include_depth==change_depth)
+/*25:*/
+#line 537 "common.w"
+{
+change_line++;
+if(!input_ln(change_file)){
+err_print("! Change file ended without @z");
+
+buffer[0]= '@';buffer[1]= 'z';limit= buffer+2;
+}
+if(limit> buffer){
+if(change_pending){
+if_section_start_make_pending(0);
+if(change_pending){
+changed_section[section_count]= 1;change_pending= 0;
+}
+}
+*limit= ' ';
+if(buffer[0]=='@'){
+if(xisupper(buffer[1]))buffer[1]= tolower(buffer[1]);
+if(buffer[1]=='x'||buffer[1]=='y'){
+loc= buffer+2;
+err_print("! Where is the matching @z?");
+
+}
+else if(buffer[1]=='z'){
+prime_the_change_buffer();changing= !changing;print_where= 1;
+}
+}
+}
+}
+
+/*:25*/
+#line 431 "common.w"
+;
+if(!changing||include_depth> change_depth){
+/*24:*/
+#line 520 "common.w"
+{
+cur_line++;
+while(!input_ln(cur_file)){
+print_where= 1;
+if(include_depth==0){input_has_ended= 1;break;}
+else{
+fclose(cur_file);include_depth--;
+if(changing&&include_depth==change_depth)break;
+cur_line++;
+}
+}
+if(!changing&&!input_has_ended)
+if(limit-buffer==change_limit-change_buffer)
+if(buffer[0]==change_buffer[0])
+if(change_limit> change_buffer)check_change();
+}
+
+/*:24*/
+#line 433 "common.w"
+;
+if(changing&&include_depth==change_depth)goto restart;
+}
+if(input_has_ended)return 0;
+loc= buffer;*limit= ' ';
+if(buffer[0]=='@'&&(buffer[1]=='i'||buffer[1]=='I')){
+loc= buffer+2;*limit= '"';
+while(*loc==' '||*loc=='\t')loc++;
+if(loc>=limit){
+err_print("! Include file name not given");
+
+goto restart;
+}
+if(include_depth>=max_include_depth-1){
+err_print("! Too many nested includes");
+
+goto restart;
+}
+include_depth++;
+/*23:*/
+#line 474 "common.w"
+{
+char temp_file_name[max_file_name_length];
+char*cur_file_name_end= cur_file_name+max_file_name_length-1;
+char*k= cur_file_name,*kk;
+int l;
+
+if(*loc=='"'){
+loc++;
+while(*loc!='"'&&k<=cur_file_name_end)*k++= *loc++;
+if(loc==limit)k= cur_file_name_end+1;
+}else
+while(*loc!=' '&&*loc!='\t'&&*loc!='"'&&k<=cur_file_name_end)*k++= *loc++;
+if(k> cur_file_name_end)too_long();
+
+*k= '\0';
+if((cur_file= fopen(cur_file_name,"r"))!=NULL){
+cur_line= 0;print_where= 1;
+goto restart;
+}
+kk= getenv("CWEBINPUTS");
+if(kk!=NULL){
+if((l= strlen(kk))> max_file_name_length-2)too_long();
+strcpy(temp_file_name,kk);
+}
+else{
+#ifdef CWEBINPUTS
+if((l= strlen(CWEBINPUTS))> max_file_name_length-2)too_long();
+strcpy(temp_file_name,CWEBINPUTS);
+#else
+l= 0;
+#endif
+}
+if(l> 0){
+if(k+l+2>=cur_file_name_end)too_long();
+
+for(;k>=cur_file_name;k--)*(k+l+1)= *k;
+strcpy(cur_file_name,temp_file_name);
+cur_file_name[l]= '/';
+if((cur_file= fopen(cur_file_name,"r"))!=NULL){
+cur_line= 0;print_where= 1;
+goto restart;
+}
+}
+include_depth--;err_print("! Cannot open include file");goto restart;
+}
+
+/*:23*/
+#line 452 "common.w"
+;
+}
+return 1;
+}
+
+/*:21*//*26:*/
+#line 569 "common.w"
+
+void
+check_complete(){
+if(change_limit!=change_buffer){
+strncpy(buffer,change_buffer,change_limit-change_buffer+1);
+limit= buffer+(int)(change_limit-change_buffer);
+changing= 1;change_depth= include_depth;loc= buffer;
+err_print("! Change file entry did not match");
+
+}
+}
+
+/*:26*//*35:*/
+#line 660 "common.w"
+
+name_pointer
+id_lookup(first,last,t)
+char*first;
+char*last;
+char t;
+{
+char*i= first;
+int h;
+int l;
+name_pointer p;
+if(last==NULL)for(last= first;*last!='\0';last++);
+l= last-first;
+/*36:*/
+#line 683 "common.w"
+
+h= (unsigned char)*i;
+while(++i<last)h= (h+h+(int)((unsigned char)*i))%hash_size;
+
+
+/*:36*/
+#line 673 "common.w"
+;
+/*37:*/
+#line 691 "common.w"
+
+p= hash[h];
+while(p&&!names_match(p,first,l,t))p= p->link;
+if(p==NULL){
+p= name_ptr;
+p->link= hash[h];hash[h]= p;
+}
+
+/*:37*/
+#line 674 "common.w"
+;
+if(p==name_ptr)/*39:*/
+#line 706 "common.w"
+{
+if(byte_ptr+l> byte_mem_end)overflow("byte memory");
+if(name_ptr>=name_dir_end)overflow("name");
+strncpy(byte_ptr,first,l);
+(++name_ptr)->byte_start= byte_ptr+= l;
+if(program==cweave)init_p(p,t);
+}
+
+/*:39*/
+#line 675 "common.w"
+;
+return(p);
+}
+
+/*:35*//*42:*/
+#line 764 "common.w"
+
+void
+print_section_name(p)
+name_pointer p;
+{
+char*ss,*s= first_chunk(p);
+name_pointer q= p+1;
+while(p!=name_dir){
+ss= (p+1)->byte_start-1;
+if(*ss==' '&&ss>=s){
+term_write(s,ss-s);p= q->link;q= p;
+}else{
+term_write(s,ss+1-s);p= name_dir;q= NULL;
+}
+s= p->byte_start;
+}
+if(q)term_write("...",3);
+}
+
+/*:42*//*43:*/
+#line 783 "common.w"
+
+void
+sprint_section_name(dest,p)
+char*dest;
+name_pointer p;
+{
+char*ss,*s= first_chunk(p);
+name_pointer q= p+1;
+while(p!=name_dir){
+ss= (p+1)->byte_start-1;
+if(*ss==' '&&ss>=s){
+p= q->link;q= p;
+}else{
+ss++;p= name_dir;
+}
+strncpy(dest,s,ss-s),dest+= ss-s;
+s= p->byte_start;
+}
+*dest= '\0';
+}
+
+/*:43*//*44:*/
+#line 804 "common.w"
+
+void
+print_prefix_name(p)
+name_pointer p;
+{
+char*s= first_chunk(p);
+int l= prefix_length(p);
+term_write(s,l);
+if(s+l<(p+1)->byte_start)term_write("...",3);
+}
+
+/*:44*//*45:*/
+#line 825 "common.w"
+
+int web_strcmp(j,j_len,k,k_len)
+char*j,*k;
+int j_len,k_len;
+{
+char*j1= j+j_len,*k1= k+k_len;
+while(k<k1&&j<j1&&*j==*k)k++,j++;
+if(k==k1)if(j==j1)return equal;
+else return extension;
+else if(j==j1)return prefix;
+else if(*j<*k)return less;
+else return greater;
+}
+
+/*:45*//*47:*/
+#line 855 "common.w"
+
+name_pointer
+add_section_name(par,c,first,last,ispref)
+name_pointer par;
+int c;
+char*first;
+char*last;
+int ispref;
+{
+name_pointer p= name_ptr;
+char*s= first_chunk(p);
+int name_len= last-first+ispref;
+if(s+name_len> byte_mem_end)overflow("byte memory");
+if(name_ptr+1>=name_dir_end)overflow("name");
+(++name_ptr)->byte_start= byte_ptr= s+name_len;
+if(ispref){
+*(byte_ptr-1)= ' ';
+name_len--;
+name_ptr->link= name_dir;
+(++name_ptr)->byte_start= byte_ptr;
+}
+set_prefix_length(p,name_len);
+strncpy(s,first,name_len);
+p->llink= NULL;
+p->rlink= NULL;
+init_node(p);
+return par==NULL?(root= p):c==less?(par->llink= p):(par->rlink= p);
+}
+
+/*:47*//*48:*/
+#line 884 "common.w"
+
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p;
+char*first;
+char*last;
+int ispref;
+{
+char*s;
+name_pointer q= p+1;
+int name_len= last-first+ispref;
+if(name_ptr>=name_dir_end)overflow("name");
+while(q->link!=name_dir)q= q->link;
+q->link= name_ptr;
+s= name_ptr->byte_start;
+name_ptr->link= name_dir;
+if(s+name_len> byte_mem_end)overflow("byte memory");
+(++name_ptr)->byte_start= byte_ptr= s+name_len;
+strncpy(s,first,name_len);
+if(ispref)*(byte_ptr-1)= ' ';
+}
+
+/*:48*//*49:*/
+#line 912 "common.w"
+
+name_pointer
+section_lookup(first,last,ispref)
+char*first,*last;
+int ispref;
+{
+int c= 0;
+name_pointer p= root;
+name_pointer q= NULL;
+name_pointer r= NULL;
+name_pointer par= NULL;
+
+int name_len= last-first+1;
+/*50:*/
+#line 936 "common.w"
+
+while(p){
+c= web_strcmp(first,name_len,first_chunk(p),prefix_length(p));
+if(c==less||c==greater){
+if(r==NULL)
+par= p;
+p= (c==less?p->llink:p->rlink);
+}else{
+if(r!=NULL){
+printf("\n! Ambiguous prefix: matches <");
+
+print_prefix_name(p);
+printf(">\n and <");
+print_prefix_name(r);
+err_print(">");
+return name_dir;
+}
+r= p;
+p= p->llink;
+q= r->rlink;
+}
+if(p==NULL)
+p= q,q= NULL;
+}
+
+/*:50*/
+#line 926 "common.w"
+;
+/*51:*/
+#line 961 "common.w"
+
+if(r==NULL)
+return add_section_name(par,c,first,last+1,ispref);
+
+/*:51*/
+#line 927 "common.w"
+;
+/*52:*/
+#line 969 "common.w"
+
+switch(section_name_cmp(&first,name_len,r)){
+
+case prefix:
+if(!ispref){
+printf("\n! New name is a prefix of <");
+
+print_section_name(r);
+err_print(">");
+}
+else if(name_len<prefix_length(r))set_prefix_length(r,name_len);
+
+case equal:return r;
+case extension:if(!ispref||first<=last)
+extend_section_name(r,first,last+1,ispref);
+return r;
+case bad_extension:
+printf("\n! New name extends <");
+
+print_section_name(r);
+err_print(">");
+return r;
+default:
+printf("\n! Section name incompatible with <");
+
+print_prefix_name(r);
+printf(">,\n which abbreviates <");
+print_section_name(r);
+err_print(">");
+return r;
+}
+
+/*:52*/
+#line 928 "common.w"
+;
+}
+
+/*:49*//*54:*/
+#line 1020 "common.w"
+
+int section_name_cmp(pfirst,len,r)
+char**pfirst;
+int len;
+name_pointer r;
+{
+char*first= *pfirst;
+name_pointer q= r+1;
+char*ss,*s= first_chunk(r);
+int c;
+int ispref;
+while(1){
+ss= (r+1)->byte_start-1;
+if(*ss==' '&&ss>=r->byte_start)ispref= 1,q= q->link;
+else ispref= 0,ss++,q= name_dir;
+switch(c= web_strcmp(first,len,s,ss-s)){
+case equal:if(q==name_dir)
+if(ispref){
+*pfirst= first+(ss-s);
+return extension;
+}else return equal;
+else return(q->byte_start==(q+1)->byte_start)?equal:prefix;
+case extension:
+if(!ispref)return bad_extension;
+first+= ss-s;
+if(q!=name_dir){len-= ss-s;s= q->byte_start;r= q;continue;}
+*pfirst= first;return extension;
+default:return c;
+}
+}
+}
+
+/*:54*//*58:*/
+#line 1095 "common.w"
+
+void
+err_print(s)
+char*s;
+{
+char*k,*l;
+printf(*s=='!'?"\n%s":"%s",s);
+if(web_file_open)/*59:*/
+#line 1115 "common.w"
+
+{if(changing&&include_depth==change_depth)
+printf(". (l. %d of change file)\n",change_line);
+else if(include_depth==0)printf(". (l. %d)\n",cur_line);
+else printf(". (l. %d of include file %s)\n",cur_line,cur_file_name);
+l= (loc>=limit?limit:loc);
+if(l> buffer){
+for(k= buffer;k<l;k++)
+if(*k=='\t')putchar(' ');
+else putchar(*k);
+putchar('\n');
+for(k= buffer;k<l;k++)putchar(' ');
+}
+for(k= l;k<limit;k++)putchar(*k);
+if(*limit=='|')putchar('|');
+putchar(' ');
+}
+
+/*:59*/
+#line 1102 "common.w"
+;
+update_terminal;mark_error;
+}
+
+/*:58*//*61:*/
+#line 1150 "common.w"
+
+int wrap_up(){
+putchar('\n');
+if(show_stats)
+print_stats();
+/*62:*/
+#line 1160 "common.w"
+
+switch(history){
+case spotless:if(show_happiness)printf("(No errors were found.)\n");break;
+case harmless_message:
+printf("(Did you see the warning message above?)\n");break;
+case error_message:
+printf("(Pardon me, but I think I spotted something wrong.)\n");break;
+case fatal_message:printf("(That was a fatal error, my friend.)\n");
+}
+
+/*:62*/
+#line 1155 "common.w"
+;
+if(history> harmless_message)return(1);
+else return(0);
+}
+
+/*:61*//*64:*/
+#line 1179 "common.w"
+void
+fatal(s,t)
+char*s,*t;
+{
+if(*s)printf(s);
+err_print(t);
+history= fatal_message;exit(wrap_up());
+}
+
+/*:64*//*65:*/
+#line 1190 "common.w"
+void
+overflow(t)
+char*t;
+{
+printf("\n! Sorry, %s capacity exceeded",t);fatal("","");
+}
+
+
+/*:65*//*70:*/
+#line 1254 "common.w"
+
+void
+scan_args()
+{
+char*dot_pos;
+char*name_pos;
+register char*s;
+boolean found_web= 0,found_change= 0,found_out= 0;
+
+boolean flag_change;
+
+while(--argc> 0){
+if((**(++argv)=='-'||**argv=='+')&&*(*argv+1))/*74:*/
+#line 1344 "common.w"
+
+{
+if(**argv=='-')flag_change= 0;
+else flag_change= 1;
+for(dot_pos= *argv+1;*dot_pos> '\0';dot_pos++)
+flags[*dot_pos]= flag_change;
+}
+
+/*:74*/
+#line 1266 "common.w"
+
+else{
+s= name_pos= *argv;dot_pos= NULL;
+while(*s){
+if(*s=='.')dot_pos= s++;
+else if(*s=='/')dot_pos= NULL,name_pos= ++s;
+else s++;
+}
+if(!found_web)/*71:*/
+#line 1292 "common.w"
+
+{
+if(s-*argv> max_file_name_length-5)
+/*76:*/
+#line 1364 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1295 "common.w"
+;
+if(dot_pos==NULL)
+sprintf(web_file_name,"%s.w",*argv);
+else{
+strcpy(web_file_name,*argv);
+*dot_pos= 0;
+}
+sprintf(alt_web_file_name,"%s.web",*argv);
+sprintf(tex_file_name,"%s.tex",name_pos);
+sprintf(idx_file_name,"%s.idx",name_pos);
+sprintf(scn_file_name,"%s.scn",name_pos);
+sprintf(C_file_name,"%s.c",name_pos);
+found_web= 1;
+}
+
+/*:71*/
+#line 1275 "common.w"
+
+else if(!found_change)/*72:*/
+#line 1310 "common.w"
+
+{
+if(strcmp(*argv,"-")==0)found_change= -1;
+else{
+if(s-*argv> max_file_name_length-4)
+/*76:*/
+#line 1364 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1315 "common.w"
+;
+if(dot_pos==NULL)
+sprintf(change_file_name,"%s.ch",*argv);
+else strcpy(change_file_name,*argv);
+found_change= 1;
+}
+}
+
+/*:72*/
+#line 1276 "common.w"
+
+else if(!found_out)/*73:*/
+#line 1323 "common.w"
+
+{
+if(s-*argv> max_file_name_length-5)
+/*76:*/
+#line 1364 "common.w"
+fatal("! Filename too long\n",*argv);
+
+
+/*:76*/
+#line 1326 "common.w"
+;
+if(dot_pos==NULL){
+sprintf(tex_file_name,"%s.tex",*argv);
+sprintf(idx_file_name,"%s.idx",*argv);
+sprintf(scn_file_name,"%s.scn",*argv);
+sprintf(C_file_name,"%s.c",*argv);
+}else{
+strcpy(tex_file_name,*argv);
+strcpy(C_file_name,*argv);
+if(flags['x']){
+*dot_pos= 0;
+sprintf(idx_file_name,"%s.idx",*argv);
+sprintf(scn_file_name,"%s.scn",*argv);
+}
+}
+found_out= 1;
+}
+
+/*:73*/
+#line 1277 "common.w"
+
+else/*75:*/
+#line 1352 "common.w"
+
+{
+if(program==ctangle)
+fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+,"");
+
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+,"");
+}
+
+/*:75*/
+#line 1278 "common.w"
+;
+}
+}
+if(!found_web)/*75:*/
+#line 1352 "common.w"
+
+{
+if(program==ctangle)
+fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+,"");
+
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+,"");
+}
+
+/*:75*/
+#line 1281 "common.w"
+;
+if(found_change<=0)strcpy(change_file_name,"/dev/null");
+}
+
+/*:70*/
diff --git a/Build/source/texk/web2c/cwebdir/common.h b/Build/source/texk/web2c/cwebdir/common.h
new file mode 100644
index 00000000000..a91b8e8d8ea
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/common.h
@@ -0,0 +1,192 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.0 --- June 1993 (works also with later versions)
+
+% Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is distributed under the terms of a
+% permission notice identical to this one.
+
+% Please send comments, suggestions, etc. to levy@@math.berkeley.edu.
+
+% The next few sections contain stuff from the file |"common.w"| that has
+% to be included in both |"ctangle.w"| and |"cweave.w"|. It appears in this
+% file |"common.h"|, which needs to be updated when |"common.w"| changes.
+
+First comes general stuff:
+
+@d ctangle 0
+@d cweave 1
+
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>=
+typedef short boolean;
+typedef char unsigned eight_bits;
+extern boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
+extern int phase; /* which phase are we in? */
+
+@ @<Include files@>=
+#include <stdio.h>
+
+@ Code related to the character set:
+@^ASCII code dependencies@>
+
+@d and_and 04 /* `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} */
+@d lt_lt 020 /* `\.{<<}'\,; corresponds to MIT's {\tentex\char'20} */
+@d gt_gt 021 /* `\.{>>}'\,; corresponds to MIT's {\tentex\char'21} */
+@d plus_plus 013 /* `\.{++}'\,; corresponds to MIT's {\tentex\char'13} */
+@d minus_minus 01 /* `\.{--}'\,; corresponds to MIT's {\tentex\char'1} */
+@d minus_gt 031 /* `\.{->}'\,; corresponds to MIT's {\tentex\char'31} */
+@d not_eq 032 /* `\.{!=}'\,; corresponds to MIT's {\tentex\char'32} */
+@d lt_eq 034 /* `\.{<=}'\,; corresponds to MIT's {\tentex\char'34} */
+@d gt_eq 035 /* `\.{>=}'\,; corresponds to MIT's {\tentex\char'35} */
+@d eq_eq 036 /* `\.{==}'\,; corresponds to MIT's {\tentex\char'36} */
+@d or_or 037 /* `\.{\v\v}'\,; corresponds to MIT's {\tentex\char'37} */
+@d dot_dot_dot 016 /* `\.{...}'\,; corresponds to MIT's {\tentex\char'16} */
+@d colon_colon 06 /* `\.{::}'\,; corresponds to MIT's {\tentex\char'6} */
+@d period_ast 026 /* `\.{.*}'\,; corresponds to MIT's {\tentex\char'26} */
+@d minus_gt_ast 027 /* `\.{->*}'\,; corresponds to MIT's {\tentex\char'27} */
+
+@<Common code...@>=
+char section_text[longest_name+1]; /* name being sought for */
+char *section_text_end = section_text+longest_name; /* end of |section_text| */
+char *id_first; /* where the current identifier begins in the buffer */
+char *id_loc; /* just after the current identifier in the buffer */
+
+@ Code related to input routines:
+
+@d xisalpha(c) (isalpha(c)&&((eight_bits)c<0200))
+@d xisdigit(c) (isdigit(c)&&((eight_bits)c<0200))
+@d xisspace(c) (isspace(c)&&((eight_bits)c<0200))
+@d xislower(c) (islower(c)&&((eight_bits)c<0200))
+@d xisupper(c) (isupper(c)&&((eight_bits)c<0200))
+@d xisxdigit(c) (isxdigit(c)&&((eight_bits)c<0200))
+
+@<Common code...@>=
+extern char buffer[]; /* where each line of input goes */
+extern char *buffer_end; /* end of |buffer| */
+extern char *loc; /* points to the next character to be read from the buffer*/
+extern char *limit; /* points to the last character in the buffer */
+
+@ Code related to identifier and section name storage:
+@d length(c) (c+1)->byte_start-(c)->byte_start /* the length of a name */
+@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */
+@d llink link /* left link in binary search tree for section names */
+@d rlink dummy.Rlink /* right link in binary search tree for section names */
+@d root name_dir->rlink /* the root of the binary search tree
+ for section names */
+@d chunk_marker 0
+
+@<Common code...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ } dummy;
+ char *equiv_or_xref; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char byte_mem[]; /* characters of names */
+extern char *byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char *byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+
+@ Code related to error handling:
+@d spotless 0 /* |history| value for normal jobs */
+@d harmless_message 1 /* |history| value when non-serious info was printed */
+@d error_message 2 /* |history| value when an error was noted */
+@d fatal_message 3 /* |history| value when we had to stop prematurely */
+@d mark_harmless {if (history==spotless) history=harmless_message;}
+@d mark_error history=error_message
+@d confusion(s) fatal("! This can't happen: ",s)
+
+@<Common...@>=
+extern history; /* indicates how bad this run was */
+extern err_print(); /* print error message and context */
+extern wrap_up(); /* indicate |history| and exit */
+extern void fatal(); /* issue error message and die */
+extern void overflow(); /* succumb because a table has overflowed */
+
+@ Code related to file handling:
+@f line x /* make |line| an unreserved word */
+@d max_file_name_length 60
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d web_file_name file_name[0] /* main source file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+
+@<Common code...@>=
+extern include_depth; /* current level of nesting */
+extern FILE *file[]; /* stack of non-change files */
+extern FILE *change_file; /* change file */
+extern char C_file_name[]; /* name of |C_file| */
+extern char tex_file_name[]; /* name of |tex_file| */
+extern char idx_file_name[]; /* name of |idx_file| */
+extern char scn_file_name[]; /* name of |scn_file| */
+extern char file_name[][max_file_name_length];
+ /* stack of non-change file names */
+extern char change_file_name[]; /* name of change file */
+extern line[]; /* number of current line in the stacked files */
+extern change_line; /* number of current line in change file */
+extern boolean input_has_ended; /* if there is no more input */
+extern boolean changing; /* if the current line is from |change_file| */
+extern boolean web_file_open; /* if the web file is being read */
+extern reset_input(); /* initialize to read the web file and change file */
+extern get_line(); /* inputs the next line */
+extern check_complete(); /* checks that all changes were picked up */
+
+@ Code related to section numbers:
+@<Common code...@>=
+typedef unsigned short sixteen_bits;
+extern sixteen_bits section_count; /* the current section number */
+extern boolean changed_section[]; /* is the section changed? */
+extern boolean change_pending; /* is a decision about change still unclear? */
+extern boolean print_where; /* tells \.{CTANGLE} to print line and file info */
+
+@ Code related to command line arguments:
+@d show_banner flags['b'] /* should the banner line be printed? */
+@d show_progress flags['p'] /* should progress reports be printed? */
+@d show_happiness flags['h'] /* should lack of errors be announced? */
+
+@<Common code...@>=
+extern int argc; /* copy of |ac| parameter to |main| */
+extern char **argv; /* copy of |av| parameter to |main| */
+extern boolean flags[]; /* an option for each 7-bit code */
+
+@ Code relating to output:
+@d update_terminal fflush(stdout) /* empty the terminal output buffer */
+@d new_line putchar('\n') @d putxchar putchar
+@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)
+@d C_printf(c,a) fprintf(C_file,c,a)
+@d C_putc(c) putc(c,C_file)
+
+@<Common code...@>=
+extern FILE *C_file; /* where output of \.{CTANGLE} goes */
+extern FILE *tex_file; /* where output of \.{CWEAVE} goes */
+extern FILE *idx_file; /* where index from \.{CWEAVE} goes */
+extern FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+extern FILE *active_file; /* currently active file for \.{CWEAVE} output */
+
+@ The procedure that gets everything rolling:
+
+@<Common code...@>=
+extern void common_init();
diff --git a/Build/source/texk/web2c/cwebdir/common.w b/Build/source/texk/web2c/cwebdir/common.w
new file mode 100644
index 00000000000..466456c306d
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/common.w
@@ -0,0 +1,1418 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.64 --- January 2002
+
+% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+\def\v{\char'174} % vertical (|) in typewriter font
+
+\def\title{Common code for CTANGLE and CWEAVE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and
+ {\ttitlefont CWEAVE}}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+@s not_eq normal @q unreserve a C++ keyword @>
+
+@** Introduction. This file contains code common
+to both \.{CTANGLE} and \.{CWEAVE}, which roughly concerns the following
+problems: character uniformity, input routines, error handling and
+parsing of command line. We have tried to concentrate in this file
+all the system dependencies, so as to maximize portability.
+
+In the texts below we will
+sometimes use \.{CWEB} to refer to either of the two component
+programs, if no confusion can arise.
+
+The file begins with a few basic definitions.
+
+@c
+@<Include files@>@/
+@h
+@<Definitions that should agree with \.{CTANGLE} and \.{CWEAVE}@>@/
+@<Other definitions@>@/
+@<Predeclaration of procedures@>@/
+
+@ In certain cases \.{CTANGLE} and \.{CWEAVE} should do almost, but not
+quite, the same thing. In these cases we've written common code for
+both, differentiating between the two by means of the global variable
+|program|.
+
+@d ctangle 0
+@d cweave 1
+
+@<Definitions...@>=
+typedef short boolean;
+boolean program; /* \.{CWEAVE} or \.{CTANGLE}? */
+
+@ \.{CWEAVE} operates in three phases: First it inputs the source
+file and stores cross-reference data, then it inputs the source once again and
+produces the \TEX/ output file, and finally it sorts and outputs the index.
+Similarly, \.{CTANGLE} operates in two phases.
+The global variable |phase| tells which phase we are in.
+
+@<Other...@>= int phase; /* which phase are we in? */
+
+@ There's an initialization procedure that gets both \.{CTANGLE} and
+\.{CWEAVE} off to a good start. We will fill in the details of this
+procedure later.
+
+@c
+void
+common_init()
+{
+ @<Initialize pointers@>;
+ @<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>;
+ @<Scan arguments and open output files@>;
+}
+
+@* The character set.
+\.{CWEB} uses the conventions of \CEE/ programs found in the standard
+\.{ctype.h} header file.
+
+@<Include files@>=
+#include <ctype.h>
+
+@ A few character pairs are encoded internally as single characters,
+using the definitions below. These definitions are consistent with
+an extension of ASCII code originally developed at MIT and explained in
+Appendix~C of {\sl The \TEX/book\/}; thus, users who have such a
+character set can type things like \.{\char'32} and \.{\char'4} instead
+of \.{!=} and \.{\&\&}. (However, their files will not be too portable
+until more people adopt the extended code.)
+
+If the character set is not ASCII, the definitions given here may conflict
+with existing characters; in such cases, other arbitrary codes should be
+substituted. The indexes to \.{CTANGLE} and \.{CWEAVE} mention every
+case where similar codes may have to be changed in order to
+avoid character conflicts. Look for the entry ``ASCII code dependencies''
+in those indexes.
+
+@^ASCII code dependencies@>
+@^system dependencies@>
+
+@d and_and 04 /* `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} */
+@d lt_lt 020 /* `\.{<<}'\,; corresponds to MIT's {\tentex\char'20} */
+@d gt_gt 021 /* `\.{>>}'\,; corresponds to MIT's {\tentex\char'21} */
+@d plus_plus 013 /* `\.{++}'\,; corresponds to MIT's {\tentex\char'13} */
+@d minus_minus 01 /* `\.{--}'\,; corresponds to MIT's {\tentex\char'1} */
+@d minus_gt 031 /* `\.{->}'\,; corresponds to MIT's {\tentex\char'31} */
+@d not_eq 032 /* `\.{!=}'\,; corresponds to MIT's {\tentex\char'32} */
+@d lt_eq 034 /* `\.{<=}'\,; corresponds to MIT's {\tentex\char'34} */
+@d gt_eq 035 /* `\.{>=}'\,; corresponds to MIT's {\tentex\char'35} */
+@d eq_eq 036 /* `\.{==}'\,; corresponds to MIT's {\tentex\char'36} */
+@d or_or 037 /* `\.{\v\v}'\,; corresponds to MIT's {\tentex\char'37} */
+@d dot_dot_dot 016 /* `\.{...}'\,; corresponds to MIT's {\tentex\char'16} */
+@d colon_colon 06 /* `\.{::}'\,; corresponds to MIT's {\tentex\char'6} */
+@d period_ast 026 /* `\.{.*}'\,; corresponds to MIT's {\tentex\char'26} */
+@d minus_gt_ast 027 /* `\.{->*}'\,; corresponds to MIT's {\tentex\char'27} */
+
+@** Input routines. The lowest level of input to the \.{CWEB} programs
+is performed by |input_ln|, which must be told which file to read from.
+The return value of |input_ln| is 1 if the read is successful and 0 if
+not (generally this means the file has ended). The conventions
+of \TEX/ are followed; i.e., the characters of the next line of the file
+are copied into the |buffer| array,
+and the global variable |limit| is set to the first unoccupied position.
+Trailing blanks are ignored. The value of |limit| must be strictly less
+than |buf_size|, so that |buffer[buf_size-1]| is never filled.
+
+Since |buf_size| is strictly less than |long_buf_size|,
+some of \.{CWEB}'s routines use the fact that it is safe to refer to
+|*(limit+2)| without overstepping the bounds of the array.
+
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+@d longest_name 1000
+@d long_buf_size (buf_size+longest_name) /* for \.{CWEAVE} */
+@d xisspace(c) (isspace(c)&&((unsigned char)c<0200))
+@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
+
+@<Definitions...@>=
+char buffer[long_buf_size]; /* where each line of input goes */
+char *buffer_end=buffer+buf_size-2; /* end of |buffer| */
+char *limit=buffer; /* points to the last character in the buffer */
+char *loc=buffer; /* points to the next character to be read from the buffer */
+
+@ @<Include files@>=
+#include <stdio.h>
+
+@ In the unlikely event that your standard I/O library does not
+support |feof|, |getc|, and |ungetc| you may have to change things here.
+@^system dependencies@>
+
+@c
+int input_ln(fp) /* copies a line into |buffer| or returns 0 */
+FILE *fp; /* what file to read from */
+{
+ register int c=EOF; /* character read; initialized so some compilers won't complain */
+ register char *k; /* where next character goes */
+ if (feof(fp)) return(0); /* we have hit end-of-file */
+ limit = k = buffer; /* beginning of buffer */
+ while (k<=buffer_end && (c=getc(fp)) != EOF && c!='\n')
+ if ((*(k++) = c) != ' ') limit = k;
+ if (k>buffer_end)
+ if ((c=getc(fp))!=EOF && c!='\n') {
+ ungetc(c,fp); loc=buffer; err_print("! Input line too long");
+@.Input line too long@>
+ }
+ if (c==EOF && limit==buffer) return(0); /* there was nothing after
+ the last newline */
+ return(1);
+}
+
+@ Now comes the problem of deciding which file to read from next.
+Recall that the actual text that \.{CWEB} should process comes from two
+streams: a |web_file|, which can contain possibly nested include
+commands \.{@@i}, and a |change_file|, which might also contain
+includes. The |web_file| together with the currently open include
+files form a stack |file|, whose names are stored in a parallel stack
+|file_name|. The boolean |changing| tells whether or not we're reading
+from the |change_file|.
+
+The line number of each open file is also kept for error reporting and
+for the benefit of \.{CTANGLE}.
+
+@f line x /* make |line| an unreserved word */
+@d max_include_depth 10 /* maximum number of source files open
+ simultaneously, not counting the change file */
+@d max_file_name_length 60
+@d cur_file file[include_depth] /* current file */
+@d cur_file_name file_name[include_depth] /* current file name */
+@d cur_line line[include_depth] /* number of current line in current file */
+@d web_file file[0] /* main source file */
+@d web_file_name file_name[0] /* main source file name */
+
+@<Definitions...@>=
+int include_depth; /* current level of nesting */
+FILE *file[max_include_depth]; /* stack of non-change files */
+FILE *change_file; /* change file */
+char file_name[max_include_depth][max_file_name_length];
+ /* stack of non-change file names */
+char change_file_name[max_file_name_length]; /* name of change file */
+char alt_web_file_name[max_file_name_length]; /* alternate name to try */
+int line[max_include_depth]; /* number of current line in the stacked files */
+int change_line; /* number of current line in change file */
+int change_depth; /* where \.{@@y} originated during a change */
+boolean input_has_ended; /* if there is no more input */
+boolean changing; /* if the current line is from |change_file| */
+boolean web_file_open=0; /* if the web file is being read */
+
+@ When |changing==0|, the next line of |change_file| is kept in
+|change_buffer|, for purposes of comparison with the next
+line of |cur_file|. After the change file has been completely input, we
+set |change_limit=change_buffer|,
+so that no further matches will be made.
+
+Here's a shorthand expression for inequality between the two lines:
+
+@d lines_dont_match (change_limit-change_buffer != limit-buffer ||
+ strncmp(buffer, change_buffer, limit-buffer))
+
+@<Other...@>=
+char change_buffer[buf_size]; /* next line of |change_file| */
+char *change_limit; /* points to the last character in |change_buffer| */
+
+@ Procedure |prime_the_change_buffer|
+sets |change_buffer| in preparation for the next matching operation.
+Since blank lines in the change file are not used for matching, we have
+|(change_limit==change_buffer && !changing)| if and only if
+the change file is exhausted. This procedure is called only when
+|changing| is 1; hence error messages will be reported correctly.
+
+@c
+void
+prime_the_change_buffer()
+{
+ change_limit=change_buffer; /* this value is used if the change file ends */
+ @<Skip over comment lines in the change file; |return| if end of file@>;
+ @<Skip to the next nonblank line; |return| if end of file@>;
+ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+}
+
+@ While looking for a line that begins with \.{@@x} in the change file, we
+allow lines that begin with \.{@@}, as long as they don't begin with \.{@@y},
+\.{@@z}, or \.{@@i} (which would probably mean that the change file is fouled up).
+
+@<Skip over comment lines in the change file...@>=
+while(1) {
+ change_line++;
+ if (!input_ln(change_file)) return;
+ if (limit<buffer+2) continue;
+ if (buffer[0]!='@@') continue;
+ if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (buffer[1]=='x') break;
+ if (buffer[1]=='y' || buffer[1]=='z' || buffer[1]=='i') {
+ loc=buffer+2;
+ err_print("! Missing @@x in change file");
+@.Missing @@x...@>
+ }
+}
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do {
+ change_line++;
+ if (!input_ln(change_file)) {
+ err_print("! Change file ended after @@x");
+@.Change file ended...@>
+ return;
+ }
+} while (limit==buffer);
+
+@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+{
+ change_limit=change_buffer+(limit-buffer);
+ strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+@ The following procedure is used to see if the next change entry should
+go into effect; it is called only when |changing| is 0.
+The idea is to test whether or not the current
+contents of |buffer| matches the current contents of |change_buffer|.
+If not, there's nothing more to do; but if so, a change is called for:
+All of the text down to the \.{@@y} is supposed to match. An error
+message is issued if any discrepancy is found. Then the procedure
+prepares to read the next line from |change_file|.
+
+When a match is found, the current section is marked as changed unless
+the first line after the \.{@@x} and after the \.{@@y} both start with
+either |'@@*'| or |'@@ '| (possibly preceded by whitespace).
+
+This procedure is called only when |buffer<limit|, i.e., when the
+current line is nonempty.
+
+@d if_section_start_make_pending(b) {@+*limit='!';
+ for (loc=buffer;xisspace(*loc);loc++) ;
+ *limit=' ';
+ if (*loc=='@@' && (xisspace(*(loc+1)) || *(loc+1)=='*')) change_pending=b;
+}
+
+@c
+void
+check_change() /* switches to |change_file| if the buffers match */
+{
+ int n=0; /* the number of discrepancies found */
+ if (lines_dont_match) return;
+ change_pending=0;
+ if (!changed_section[section_count]) {
+ if_section_start_make_pending(1);
+ if (!change_pending) changed_section[section_count]=1;
+ }
+ while (1) {
+ changing=1; print_where=1; change_line++;
+ if (!input_ln(change_file)) {
+ err_print("! Change file ended before @@y");
+@.Change file ended...@>
+ change_limit=change_buffer; changing=0;
+ return;
+ }
+ if (limit>buffer+1 && buffer[0]=='@@') {
+ char xyz_code=xisupper(buffer[1])? tolower(buffer[1]): buffer[1];
+ @<If the current line starts with \.{@@y},
+ report any discrepancies and |return|@>;
+ }
+ @<Move |buffer| and |limit|...@>;
+ changing=0; cur_line++;
+ while (!input_ln(cur_file)) { /* pop the stack or quit */
+ if (include_depth==0) {
+ err_print("! CWEB file ended during a change");
+@.CWEB file ended...@>
+ input_has_ended=1; return;
+ }
+ include_depth--; cur_line++;
+ }
+ if (lines_dont_match) n++;
+ }
+}
+
+@ @<If the current line starts with \.{@@y}...@>=
+if (xyz_code=='x' || xyz_code=='z') {
+ loc=buffer+2; err_print("! Where is the matching @@y?");
+@.Where is the match...@>
+ }
+else if (xyz_code=='y') {
+ if (n>0) {
+ loc=buffer+2;
+ printf("\n! Hmm... %d ",n);
+ err_print("of the preceding lines failed to match");
+@.Hmm... n of the preceding...@>
+ }
+ change_depth=include_depth;
+ return;
+}
+
+@ The |reset_input| procedure, which gets \.{CWEB} ready to read the
+user's \.{CWEB} input, is used at the beginning of phase one of \.{CTANGLE},
+phases one and two of \.{CWEAVE}.
+
+@c
+void
+reset_input()
+{
+ limit=buffer; loc=buffer+1; buffer[0]=' ';
+ @<Open input files@>;
+ include_depth=0; cur_line=0; change_line=0;
+ change_depth=include_depth;
+ changing=1; prime_the_change_buffer(); changing=!changing;
+ limit=buffer; loc=buffer+1; buffer[0]=' '; input_has_ended=0;
+}
+
+@ The following code opens the input files.
+@^system dependencies@>
+
+@<Open input files@>=
+if ((web_file=fopen(web_file_name,"r"))==NULL) {
+ strcpy(web_file_name,alt_web_file_name);
+ if ((web_file=fopen(web_file_name,"r"))==NULL)
+ fatal("! Cannot open input file ", web_file_name);
+}
+@.Cannot open input file@>
+@.Cannot open change file@>
+web_file_open=1;
+if ((change_file=fopen(change_file_name,"r"))==NULL)
+ fatal("! Cannot open change file ", change_file_name);
+
+@ The |get_line| procedure is called when |loc>limit|; it puts the next
+line of merged input into the buffer and updates the other variables
+appropriately. A space is placed at the right end of the line.
+This procedure returns |!input_has_ended| because we often want to
+check the value of that variable after calling the procedure.
+
+If we've just changed from the |cur_file| to the |change_file|, or if
+the |cur_file| has changed, we tell \.{CTANGLE} to print this
+information in the \CEE/ file by means of the |print_where| flag.
+
+@d max_sections 2000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@<Defin...@>=
+typedef unsigned short sixteen_bits;
+sixteen_bits section_count; /* the current section number */
+boolean changed_section[max_sections]; /* is the section changed? */
+boolean change_pending; /* if the current change is not yet recorded in
+ |changed_section[section_count]| */
+boolean print_where=0; /* should \.{CTANGLE} print line and file info? */
+
+@ @c
+int get_line() /* inputs the next line */
+{
+ restart:
+ if (changing && include_depth==change_depth)
+ @<Read from |change_file| and maybe turn off |changing|@>;
+ if (! changing || include_depth>change_depth) {
+ @<Read from |cur_file| and maybe turn on |changing|@>;
+ if (changing && include_depth==change_depth) goto restart;
+ }
+ if (input_has_ended) return 0;
+ loc=buffer; *limit=' ';
+ if (buffer[0]=='@@' && (buffer[1]=='i' || buffer[1]=='I')) {
+ loc=buffer+2; *limit='"';
+ while (*loc==' '||*loc=='\t') loc++;
+ if (loc>=limit) {
+ err_print("! Include file name not given");
+@.Include file name ...@>
+ goto restart;
+ }
+ if (include_depth>=max_include_depth-1) {
+ err_print("! Too many nested includes");
+@.Too many nested includes@>
+ goto restart;
+ }
+ include_depth++; /* push input stack */
+ @<Try to open include file, abort push if unsuccessful, go to |restart|@>;
+ }
+ return 1;
+}
+
+@ When an \.{@@i} line is found in the |cur_file|, we must temporarily
+stop reading it and start reading from the named include file. The
+\.{@@i} line should give a complete file name with or without
+double quotes.
+If the environment variable \.{CWEBINPUTS} is set, or if the compiler flag
+of the same name was defined at compile time,
+\.{CWEB} will look for include files in the directory thus named, if
+it cannot find them in the current directory.
+(Colon-separated paths are not supported.)
+The remainder of the \.{@@i} line after the file name is ignored.
+
+@d too_long() {include_depth--;
+ err_print("! Include file name too long"); goto restart;}
+
+@<Include...@>=
+#include <stdlib.h> /* declaration of |getenv| and |exit| */
+
+@ @<Try to open...@>= {
+ char temp_file_name[max_file_name_length];
+ char *cur_file_name_end=cur_file_name+max_file_name_length-1;
+ char *k=cur_file_name, *kk;
+ int l; /* length of file name */
+
+ if (*loc=='"') {
+ loc++;
+ while (*loc!='"' && k<=cur_file_name_end) *k++=*loc++;
+ if (loc==limit) k=cur_file_name_end+1; /* unmatched quote is `too long' */
+ } else
+ while (*loc!=' '&&*loc!='\t'&&*loc!='"'&&k<=cur_file_name_end) *k++=*loc++;
+ if (k>cur_file_name_end) too_long();
+@.Include file name ...@>
+ *k='\0';
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+ cur_line=0; print_where=1;
+ goto restart; /* success */
+ }
+ kk=getenv("CWEBINPUTS");
+ if (kk!=NULL) {
+ if ((l=strlen(kk))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,kk);
+ }
+ else {
+#ifdef CWEBINPUTS
+ if ((l=strlen(CWEBINPUTS))>max_file_name_length-2) too_long();
+ strcpy(temp_file_name,CWEBINPUTS);
+#else
+ l=0;
+#endif /* |CWEBINPUTS| */
+ }
+ if (l>0) {
+ if (k+l+2>=cur_file_name_end) too_long();
+@.Include file name ...@>
+ for (; k>= cur_file_name; k--) *(k+l+1)=*k;
+ strcpy(cur_file_name,temp_file_name);
+ cur_file_name[l]='/'; /* \UNIX/ pathname separator */
+ if ((cur_file=fopen(cur_file_name,"r"))!=NULL) {
+ cur_line=0; print_where=1;
+ goto restart; /* success */
+ }
+ }
+ include_depth--; err_print("! Cannot open include file"); goto restart;
+}
+
+@ @<Read from |cur_file|...@>= {
+ cur_line++;
+ while (!input_ln(cur_file)) { /* pop the stack or quit */
+ print_where=1;
+ if (include_depth==0) {input_has_ended=1; break;}
+ else {
+ fclose(cur_file); include_depth--;
+ if (changing && include_depth==change_depth) break;
+ cur_line++;
+ }
+ }
+ if (!changing && !input_has_ended)
+ if (limit-buffer==change_limit-change_buffer)
+ if (buffer[0]==change_buffer[0])
+ if (change_limit>change_buffer) check_change();
+}
+
+@ @<Read from |change_file|...@>= {
+ change_line++;
+ if (!input_ln(change_file)) {
+ err_print("! Change file ended without @@z");
+@.Change file ended...@>
+ buffer[0]='@@'; buffer[1]='z'; limit=buffer+2;
+ }
+ if (limit>buffer) { /* check if the change has ended */
+ if (change_pending) {
+ if_section_start_make_pending(0);
+ if (change_pending) {
+ changed_section[section_count]=1; change_pending=0;
+ }
+ }
+ *limit=' ';
+ if (buffer[0]=='@@') {
+ if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (buffer[1]=='x' || buffer[1]=='y') {
+ loc=buffer+2;
+ err_print("! Where is the matching @@z?");
+@.Where is the match...@>
+ }
+ else if (buffer[1]=='z') {
+ prime_the_change_buffer(); changing=!changing; print_where=1;
+ }
+ }
+ }
+}
+
+@ At the end of the program, we will tell the user if the change file
+had a line that didn't match any relevant line in |web_file|.
+
+@c
+void
+check_complete(){
+ if (change_limit!=change_buffer) { /* |changing| is 0 */
+ strncpy(buffer,change_buffer,change_limit-change_buffer+1);
+ limit=buffer+(int)(change_limit-change_buffer);
+ changing=1; change_depth=include_depth; loc=buffer;
+ err_print("! Change file entry did not match");
+@.Change file entry did not match@>
+ }
+}
+
+@** Storage of names and strings.
+Both \.{CWEAVE} and \.{CTANGLE} store identifiers, section names and
+other strings in a large array of |char|s, called |byte_mem|.
+Information about the names is kept in the array |name_dir|, whose
+elements are structures of type |name_info|, containing a pointer into
+the |byte_mem| array (the address where the name begins) and other data.
+A |name_pointer| variable is a pointer into |name_dir|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; must be less than $2^{24}$ */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240 */
+
+@<Definitions that...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ @<More elements of |name_info| structure@>@;
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of |name_info|s */
+char byte_mem[max_bytes]; /* characters of names */
+char *byte_mem_end = byte_mem+max_bytes-1; /* end of |byte_mem| */
+name_info name_dir[max_names]; /* information about names */
+name_pointer name_dir_end = name_dir+max_names-1; /* end of |name_dir| */
+
+@ The actual sequence of characters in the name pointed to by a |name_pointer
+p| appears in positions |p->byte_start| to |(p+1)->byte_start-1|, inclusive.
+The |print_id| macro prints this text on the user's terminal.
+
+@d length(c) (c+1)->byte_start-(c)->byte_start /* the length of a name */
+@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */
+
+@ The first unused position in |byte_mem| and |name_dir| is
+kept in |byte_ptr| and |name_ptr|, respectively. Thus we
+usually have |name_ptr->byte_start==byte_ptr|, and certainly
+we want to keep |name_ptr<=name_dir_end| and |byte_ptr<=byte_mem_end|.
+
+@<Defini...@>=
+name_pointer name_ptr; /* first unused position in |byte_start| */
+char *byte_ptr; /* first unused position in |byte_mem| */
+
+@ @<Init...@>=
+name_dir->byte_start=byte_ptr=byte_mem; /* position zero in both arrays */
+name_ptr=name_dir+1; /* |name_dir[0]| will be used only for error recovery */
+name_ptr->byte_start=byte_mem; /* this makes name 0 of length zero */
+
+@ The names of identifiers are found by computing a hash address |h| and
+then looking at strings of bytes signified by the |name_pointer|s
+|hash[h]|, |hash[h]->link|, |hash[h]->link->link|, \dots,
+until either finding the desired name or encountering the null pointer.
+
+@<More elements of |name...@>=
+struct name_info *link;
+
+@ The hash table itself
+consists of |hash_size| entries of type |name_pointer|, and is
+updated by the |id_lookup| procedure, which finds a given identifier
+and returns the appropriate |name_pointer|. The matching is done by the
+function |names_match|, which is slightly different in
+\.{CWEAVE} and \.{CTANGLE}. If there is no match for the identifier,
+it is inserted into the table.
+
+@d hash_size 353 /* should be prime */
+
+@<Defini...@>=
+typedef name_pointer *hash_pointer;
+name_pointer hash[hash_size]; /* heads of hash lists */
+hash_pointer hash_end = hash+hash_size-1; /* end of |hash| */
+hash_pointer h; /* index into hash-head array */
+
+@ @<Predec...@>=
+extern int names_match();
+
+@ Initially all the hash lists are empty.
+
+@<Init...@>=
+for (h=hash; h<=hash_end; *h++=NULL) ;
+
+@ Here is the main procedure for finding identifiers:
+
+@c
+name_pointer
+id_lookup(first,last,t) /* looks up a string in the identifier table */
+char *first; /* first character of string */
+char *last; /* last character of string plus one */
+char t; /* the |ilk|; used by \.{CWEAVE} only */
+{
+ char *i=first; /* position in |buffer| */
+ int h; /* hash code */
+ int l; /* length of the given identifier */
+ name_pointer p; /* where the identifier is being sought */
+ if (last==NULL) for (last=first; *last!='\0'; last++);
+ l=last-first; /* compute the length */
+ @<Compute the hash code |h|@>;
+ @<Compute the name location |p|@>;
+ if (p==name_ptr) @<Enter a new name into the table at position |p|@>;
+ return(p);
+}
+
+@ A simple hash code is used: If the sequence of
+character codes is $c_1c_2\ldots c_n$, its hash value will be
+$$(2^{n-1}c_1+2^{n-2}c_2+\cdots+c_n)\,\bmod\,|hash_size|.$$
+
+@<Compute the hash...@>=
+h=(unsigned char)*i;
+while (++i<last) h=(h+h+(int)((unsigned char)*i)) % hash_size;
+@^high-bit character handling@>
+
+@ If the identifier is new, it will be placed in position |p=name_ptr|,
+otherwise |p| will point to its existing location.
+
+@<Compute the name location...@>=
+p=hash[h];
+while (p && !names_match(p,first,l,t)) p=p->link;
+if (p==NULL) {
+ p=name_ptr; /* the current identifier is new */
+ p->link=hash[h]; hash[h]=p; /* insert |p| at beginning of hash list */
+}
+
+@ The information associated with a new identifier must be initialized
+in a slightly different way in \.{CWEAVE} than in \.{CTANGLE}; hence the
+|init_p| procedure.
+
+@<Pred...@>=
+void init_p();
+
+@ @<Enter a new name...@>= {
+ if (byte_ptr+l>byte_mem_end) overflow("byte memory");
+ if (name_ptr>=name_dir_end) overflow("name");
+ strncpy(byte_ptr,first,l);
+ (++name_ptr)->byte_start=byte_ptr+=l;
+ if (program==cweave) init_p(p,t);
+}
+
+@ The names of sections are stored in |byte_mem| together
+with the identifier names, but a hash table is not used for them because
+\.{CTANGLE} needs to be able to recognize a section name when given a prefix of
+that name. A conventional binary search tree is used to retrieve section names,
+with fields called |llink| and |rlink| (where |llink| takes the place
+of |link|). The root of this tree is stored in |name_dir->rlink|;
+this will be the only information in |name_dir[0]|.
+
+Since the space used by |rlink| has a different function for
+identifiers than for section names, we declare it as a |union|.
+
+@d llink link /* left link in binary search tree for section names */
+@d rlink dummy.Rlink /* right link in binary search tree for section names */
+@d root name_dir->rlink /* the root of the binary search tree
+ for section names */
+
+@<More elements of |name...@>=
+union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+} dummy;
+
+@ @<Init...@>=
+root=NULL; /* the binary search tree starts out with nothing in it */
+
+@ If |p| is a |name_pointer| variable, as we have seen,
+|p->byte_start| is the beginning of the area where the name
+corresponding to |p| is stored. However, if |p| refers to a section
+name, the name may need to be stored in chunks, because it may
+``grow'': a prefix of the section name may be encountered before
+the full name. Furthermore we need to know the length of the shortest
+prefix of the name that was ever encountered.
+
+We solve this problem by inserting two extra bytes at |p->byte_start|,
+representing the length of the shortest prefix, when |p| is a
+section name. Furthermore, the last byte of the name will be a blank
+space if |p| is a prefix. In the latter case, the name pointer
+|p+1| will allow us to access additional chunks of the name:
+The second chunk will begin at the name pointer |(p+1)->link|,
+and if it too is a prefix (ending with blank) its |link| will point
+to additional chunks in the same way. Null links are represented by
+|name_dir|.
+
+@d first_chunk(p) ((p)->byte_start+2)
+@d prefix_length(p) (int)((unsigned char)*((p)->byte_start)*256 +
+ (unsigned char)*((p)->byte_start+1))
+@d set_prefix_length(p,m) (*((p)->byte_start)=(m)/256,
+ *((p)->byte_start+1)=(m)%256)
+
+@c
+void
+print_section_name(p)
+name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+ name_pointer q = p+1;
+ while (p!=name_dir) {
+ ss = (p+1)->byte_start-1;
+ if (*ss==' ' && ss>=s) {
+ term_write(s,ss-s); p=q->link; q=p;
+ } else {
+ term_write(s,ss+1-s); p=name_dir; q=NULL;
+ }
+ s = p->byte_start;
+ }
+ if (q) term_write("...",3); /* complete name not yet known */
+}
+
+@ @c
+void
+sprint_section_name(dest,p)
+ char*dest;
+ name_pointer p;
+{
+ char *ss, *s = first_chunk(p);
+ name_pointer q = p+1;
+ while (p!=name_dir) {
+ ss = (p+1)->byte_start-1;
+ if (*ss==' ' && ss>=s) {
+ p=q->link; q=p;
+ } else {
+ ss++; p=name_dir;
+ }
+ strncpy(dest,s,ss-s), dest+=ss-s;
+ s = p->byte_start;
+ }
+ *dest='\0';
+}
+
+@ @c
+void
+print_prefix_name(p)
+name_pointer p;
+{
+ char *s = first_chunk(p);
+ int l = prefix_length(p);
+ term_write(s,l);
+ if (s+l<(p+1)->byte_start) term_write("...",3);
+}
+
+@ When we compare two section names, we'll need a function analogous to
+|strcmp|. But we do not assume the strings
+are null-terminated, and we keep an eye open for prefixes and extensions.
+
+@d less 0 /* the first name is lexicographically less than the second */
+@d equal 1 /* the first name is equal to the second */
+@d greater 2 /* the first name is lexicographically greater than the second */
+@d prefix 3 /* the first name is a proper prefix of the second */
+@d extension 4 /* the first name is a proper extension of the second */
+
+@c
+int web_strcmp(j,j_len,k,k_len) /* fuller comparison than |strcmp| */
+ char *j, *k; /* beginning of first and second strings */
+ int j_len, k_len; /* length of strings */
+{
+ char *j1=j+j_len, *k1=k+k_len;
+ while (k<k1 && j<j1 && *j==*k) k++, j++;
+ if (k==k1) if (j==j1) return equal;
+ else return extension;
+ else if (j==j1) return prefix;
+ else if (*j<*k) return less;
+ else return greater;
+}
+
+@ Adding a section name to the tree is straightforward if we know its
+parent and whether it's the |rlink| or |llink| of the parent. As a
+special case, when the name is the first section being added, we set the
+``parent'' to |NULL|. When a section name is created, it has only one
+chunk, which however may be just a prefix; the full name will
+hopefully be unveiled later. Obviously, |prefix_length| starts
+out as the length of the first chunk, though it may decrease later.
+
+The information associated with a new node must be initialized
+differently in \.{CWEAVE} and \.{CTANGLE}; hence the
+|init_node| procedure, which is defined differently in \.{cweave.w}
+and \.{ctangle.w}.
+
+@<Prede...@>=
+extern void init_node();
+
+@ @c
+name_pointer
+add_section_name(par,c,first,last,ispref) /* install a new node in the tree */
+name_pointer par; /* parent of new node */
+int c; /* right or left? */
+char *first; /* first character of section name */
+char *last; /* last character of section name, plus one */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ name_pointer p=name_ptr; /* new node */
+ char *s=first_chunk(p);
+ int name_len=last-first+ispref; /* length of section name */
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+ if (name_ptr+1>=name_dir_end) overflow("name");
+ (++name_ptr)->byte_start=byte_ptr=s+name_len;
+ if (ispref) {
+ *(byte_ptr-1)=' ';
+ name_len--;
+ name_ptr->link=name_dir;
+ (++name_ptr)->byte_start=byte_ptr;
+ }
+ set_prefix_length(p,name_len);
+ strncpy(s,first,name_len);
+ p->llink=NULL;
+ p->rlink=NULL;
+ init_node(p);
+ return par==NULL ? (root=p) : c==less ? (par->llink=p) : (par->rlink=p);
+}
+
+@ @c
+void
+extend_section_name(p,first,last,ispref)
+name_pointer p; /* name to be extended */
+char *first; /* beginning of extension text */
+char *last; /* one beyond end of extension text */
+int ispref; /* are we adding a prefix or a full name? */
+{
+ char *s;
+ name_pointer q=p+1;
+ int name_len=last-first+ispref;
+ if (name_ptr>=name_dir_end) overflow("name");
+ while (q->link!=name_dir) q=q->link;
+ q->link=name_ptr;
+ s=name_ptr->byte_start;
+ name_ptr->link=name_dir;
+ if (s+name_len>byte_mem_end) overflow("byte memory");
+ (++name_ptr)->byte_start=byte_ptr=s+name_len;
+ strncpy(s,first,name_len);
+ if (ispref) *(byte_ptr-1)=' ';
+}
+
+@ The |section_lookup| procedure is supposed to find a
+section name that matches a new name, installing the new name if
+it doesn't match an existing one. The new name is the string
+between |first| and |last|; a ``match'' means that the new name
+exactly equals or is a prefix or extension of a name in the tree.
+
+@c
+name_pointer
+section_lookup(first,last,ispref) /* find or install section name in tree */
+char *first, *last; /* first and last characters of new name */
+int ispref; /* is the new name a prefix or a full name? */
+{
+ int c=0; /* comparison between two names; initialized so some compilers won't complain */
+ name_pointer p=root; /* current node of the search tree */
+ name_pointer q=NULL; /* another place to look in the tree */
+ name_pointer r=NULL; /* where a match has been found */
+ name_pointer par=NULL; /* parent of |p|, if |r| is |NULL|;
+ otherwise parent of |r| */
+ int name_len=last-first+1;
+ @<Look for matches for new name among shortest prefixes, complaining
+ if more than one is found@>;
+ @<If no match found, add new name to tree@>;
+ @<If one match found, check for compatibility and return match@>;
+}
+
+@ A legal new name matches an existing section name if and only if it
+matches the shortest prefix of that section name. Therefore we can
+limit our search for matches to shortest prefixes, which eliminates
+the need for chunk-chasing at this stage.
+
+@<Look for matches for new name among...@>=
+while (p) { /* compare shortest prefix of |p| with new name */
+ c=web_strcmp(first,name_len,first_chunk(p),prefix_length(p));
+ if (c==less || c==greater) { /* new name does not match |p| */
+ if (r==NULL) /* no previous matches have been found */
+ par=p;
+ p=(c==less?p->llink:p->rlink);
+ } else { /* new name matches |p| */
+ if (r!=NULL) { /* and also |r|: illegal */
+ printf("\n! Ambiguous prefix: matches <");
+@.Ambiguous prefix ... @>
+ print_prefix_name(p);
+ printf(">\n and <");
+ print_prefix_name(r);
+ err_print(">");
+ return name_dir; /* the unsection */
+ }
+ r=p; /* remember match */
+ p=p->llink; /* try another */
+ q=r->rlink; /* we'll get back here if the new |p| doesn't match */
+ }
+ if (p==NULL)
+ p=q, q=NULL; /* |q| held the other branch of |r| */
+}
+
+@ @<If no match ...@>=
+ if (r==NULL) /* no matches were found */
+ return add_section_name(par,c,first,last+1,ispref);
+
+@ Although error messages are given in anomalous cases, we do return the
+unique best match when a discrepancy is found, because users often
+change a title in one place while forgetting to change it elsewhere.
+
+@<If one match found, check for compatibility and return match@>=
+switch(section_name_cmp(&first,name_len,r)) {
+ /* compare all of |r| with new name */
+ case prefix:
+ if (!ispref) {
+ printf("\n! New name is a prefix of <");
+@.New name is a prefix...@>
+ print_section_name(r);
+ err_print(">");
+ }
+ else if (name_len<prefix_length(r)) set_prefix_length(r,name_len);
+ /* fall through */
+ case equal: return r;
+ case extension: if (!ispref || first<=last)
+ extend_section_name(r,first,last+1,ispref);
+ return r;
+ case bad_extension:
+ printf("\n! New name extends <");
+@.New name extends...@>
+ print_section_name(r);
+ err_print(">");
+ return r;
+ default: /* no match: illegal */
+ printf("\n! Section name incompatible with <");
+@.Section name incompatible...@>
+ print_prefix_name(r);
+ printf(">,\n which abbreviates <");
+ print_section_name(r);
+ err_print(">");
+ return r;
+}
+
+@ The return codes of |section_name_cmp|, which compares a string with
+the full name of a section, are those of |web_strcmp| plus
+|bad_extension|, used when the string is an extension of a
+supposedly already complete section name. This function has a side
+effect when the comparison string is an extension: It advances the
+address of the first character of the string by an amount equal to
+the length of the known part of the section name.
+
+The name \.{@@<foo...@@>} should be an acceptable ``abbreviation''
+for \.{@@<foo@@>}. If such an abbreviation comes after the complete
+name, there's no trouble recognizing it. If it comes before the
+complete name, we simply append a null chunk. This logic requires
+us to regard \.{@@<foo...@@>} as an ``extension'' of itself.
+
+@d bad_extension 5
+
+@<Predec...@>=
+int section_name_cmp();
+
+@ @c
+int section_name_cmp(pfirst,len,r)
+char **pfirst; /* pointer to beginning of comparison string */
+int len; /* length of string */
+name_pointer r; /* section name being compared */
+{
+ char *first=*pfirst; /* beginning of comparison string */
+ name_pointer q=r+1; /* access to subsequent chunks */
+ char *ss, *s=first_chunk(r);
+ int c; /* comparison */
+ int ispref; /* is chunk |r| a prefix? */
+ while (1) {
+ ss=(r+1)->byte_start-1;
+ if (*ss==' ' && ss>=r->byte_start) ispref=1,q=q->link;
+ else ispref=0,ss++,q=name_dir;
+ switch(c=web_strcmp(first,len,s,ss-s)) {
+ case equal: if (q==name_dir)
+ if (ispref) {
+ *pfirst=first+(ss-s);
+ return extension; /* null extension */
+ } else return equal;
+ else return (q->byte_start==(q+1)->byte_start)? equal: prefix;
+ case extension:
+ if (!ispref) return bad_extension;
+ first += ss-s;
+ if (q!=name_dir) {len -= ss-s; s=q->byte_start; r=q; continue;}
+ *pfirst=first; return extension;
+ default: return c;
+ }
+ }
+}
+
+@ The last component of |name_info| is different for \.{CTANGLE} and
+\.{CWEAVE}. In \.{CTANGLE}, if |p| is a pointer to a section name,
+|p->equiv| is a pointer to its replacement text, an element of the
+array |text_info|. In \.{CWEAVE}, on the other hand, if
+|p| points to an identifier, |p->xref| is a pointer to its
+list of cross-references, an element of the array |xmem|. The make-up
+of |text_info| and |xmem| is discussed in the \.{CTANGLE} and \.{CWEAVE}
+source files, respectively; here we just declare a common field
+|equiv_or_xref| as a pointer to a |char|.
+
+@<More elements of |name...@>=
+char *equiv_or_xref; /* info corresponding to names */
+
+@** Reporting errors to the user.
+A global variable called |history| will contain one of four values
+at the end of every run: |spotless| means that no unusual messages were
+printed; |harmless_message| means that a message of possible interest
+was printed but no serious errors were detected; |error_message| means that
+at least one error was found; |fatal_message| means that the program
+terminated abnormally. The value of |history| does not influence the
+behavior of the program; it is simply computed for the convenience
+of systems that might want to use such information.
+
+@d spotless 0 /* |history| value for normal jobs */
+@d harmless_message 1 /* |history| value when non-serious info was printed */
+@d error_message 2 /* |history| value when an error was noted */
+@d fatal_message 3 /* |history| value when we had to stop prematurely */
+@d mark_harmless {if (history==spotless) history=harmless_message;}
+@d mark_error history=error_message
+
+@<Definit...@>=
+int history=spotless; /* indicates how bad this run was */
+
+@ The command `|err_print("! Error message")|' will report a syntax error to
+the user, by printing the error message at the beginning of a new line and
+then giving an indication of where the error was spotted in the source file.
+Note that no period follows the error message, since the error routine
+will automatically supply a period. A newline is automatically supplied
+if the string begins with |"!"|.
+
+@<Predecl...@>=
+void err_print();
+
+@ @c
+void
+err_print(s) /* prints `\..' and location of error message */
+char *s;
+{
+ char *k,*l; /* pointers into |buffer| */
+ printf(*s=='!'? "\n%s" : "%s",s);
+ if(web_file_open) @<Print error location based on input buffer@>;
+ update_terminal; mark_error;
+}
+
+@ The error locations can be indicated by using the global variables
+|loc|, |cur_line|, |cur_file_name| and |changing|,
+which tell respectively the first
+unlooked-at position in |buffer|, the current line number, the current
+file, and whether the current line is from |change_file| or |cur_file|.
+This routine should be modified on systems whose standard text editor
+has special line-numbering conventions.
+@^system dependencies@>
+
+@<Print error location based on input buffer@>=
+{if (changing && include_depth==change_depth)
+ printf(". (l. %d of change file)\n", change_line);
+else if (include_depth==0) printf(". (l. %d)\n", cur_line);
+ else printf(". (l. %d of include file %s)\n", cur_line, cur_file_name);
+l= (loc>=limit? limit: loc);
+if (l>buffer) {
+ for (k=buffer; k<l; k++)
+ if (*k=='\t') putchar(' ');
+ else putchar(*k); /* print the characters already read */
+ putchar('\n');
+ for (k=buffer; k<l; k++) putchar(' '); /* space out the next line */
+}
+for (k=l; k<limit; k++) putchar(*k); /* print the part not yet read */
+if (*limit=='|') putchar('|'); /* end of \CEE/ text in section names */
+putchar(' '); /* to separate the message from future asterisks */
+}
+
+@ When no recovery from some error has been provided, we have to wrap
+up and quit as graciously as possible. This is done by calling the
+function |wrap_up| at the end of the code.
+
+\.{CTANGLE} and \.{CWEAVE} have their own notions about how to
+print the job statistics.
+
+@<Prede...@>=
+int wrap_up();
+extern void print_stats();
+
+@ Some implementations may wish to pass the |history| value to the
+operating system so that it can be used to govern whether or not other
+programs are started. Here, for instance, we pass the operating system
+a status of 0 if and only if only harmless messages were printed.
+@^system dependencies@>
+
+@c
+int wrap_up() {
+ putchar('\n');
+ if (show_stats)
+ print_stats(); /* print statistics about memory usage */
+ @<Print the job |history|@>;
+ if (history > harmless_message) return(1);
+ else return(0);
+}
+
+@ @<Print the job |history|@>=
+switch (history) {
+case spotless: if (show_happiness) printf("(No errors were found.)\n"); break;
+case harmless_message:
+ printf("(Did you see the warning message above?)\n"); break;
+case error_message:
+ printf("(Pardon me, but I think I spotted something wrong.)\n"); break;
+case fatal_message: printf("(That was a fatal error, my friend.)\n");
+} /* there are no other cases */
+
+@ When there is no way to recover from an error, the |fatal| subroutine is
+invoked. This happens most often when |overflow| occurs.
+
+@<Predec...@>=
+void fatal(), overflow();
+
+@ The two parameters to |fatal| are strings that are essentially
+concatenated to print the final error message.
+
+@c void
+fatal(s,t)
+ char *s,*t;
+{
+ if (*s) printf(s);
+ err_print(t);
+ history=fatal_message; exit(wrap_up());
+}
+
+@ An overflow stop occurs if \.{CWEB}'s tables aren't large enough.
+
+@c void
+overflow(t)
+ char *t;
+{
+ printf("\n! Sorry, %s capacity exceeded",t); fatal("","");
+}
+@.Sorry, capacity exceeded@>
+
+@ Sometimes the program's behavior is far different from what it should be,
+and \.{CWEB} prints an error message that is really for the \.{CWEB}
+maintenance person, not the user. In such cases the program says
+|confusion("indication of where we are")|.
+
+@d confusion(s) fatal("! This can't happen: ",s)
+@.This can't happen@>
+
+@** Command line arguments.
+The user calls \.{CWEAVE} and \.{CTANGLE} with arguments on the command line.
+These are either file names or flags to be turned off (beginning with |"-"|)
+or flags to be turned on (beginning with |"+"|).
+The following globals are for communicating the user's desires to the rest
+of the program. The various file name variables contain strings with
+the names of those files. Most of the 128 flags are undefined but available
+for future extensions.
+
+@d show_banner flags['b'] /* should the banner line be printed? */
+@d show_progress flags['p'] /* should progress reports be printed? */
+@d show_stats flags['s'] /* should statistics be printed at end of run? */
+@d show_happiness flags['h'] /* should lack of errors be announced? */
+
+@<Defin...@>=
+int argc; /* copy of |ac| parameter to |main| */
+char **argv; /* copy of |av| parameter to |main| */
+char C_file_name[max_file_name_length]; /* name of |C_file| */
+char tex_file_name[max_file_name_length]; /* name of |tex_file| */
+char idx_file_name[max_file_name_length]; /* name of |idx_file| */
+char scn_file_name[max_file_name_length]; /* name of |scn_file| */
+boolean flags[128]; /* an option for each 7-bit code */
+
+@ The |flags| will be initially zero. Some of them are set to~1 before
+scanning the arguments; if additional flags are 1 by default they
+should be set before calling |common_init|.
+
+@<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>=
+show_banner=show_happiness=show_progress=1;
+
+@ We now must look at the command line arguments and set the file names
+accordingly. At least one file name must be present: the \.{CWEB}
+file. It may have an extension, or it may omit the extension to get |".w"| or
+|".web"| added. The \TEX/ output file name is formed by replacing the \.{CWEB}
+file name extension by |".tex"|, and the \CEE/ file name by replacing
+the extension by |".c"|, after removing the directory name (if any).
+
+If there is a second file name present among the arguments, it is the
+change file, again either with an extension or without one to get |".ch"|.
+An omitted change file argument means that |"/dev/null"| should be used,
+when no changes are desired.
+@^system dependencies@>
+
+If there's a third file name, it will be the output file.
+
+@<Pred...@>=
+void scan_args();
+
+@ @c
+void
+scan_args()
+{
+ char *dot_pos; /* position of |'.'| in the argument */
+ char *name_pos; /* file name beginning, sans directory */
+ register char *s; /* register for scanning strings */
+ boolean found_web=0,found_change=0,found_out=0;
+ /* have these names been seen? */
+ boolean flag_change;
+
+ while (--argc > 0) {
+ if ((**(++argv)=='-'||**argv=='+')&&*(*argv+1)) @<Handle flag argument@>@;
+ else {
+ s=name_pos=*argv;@+dot_pos=NULL;
+ while (*s) {
+ if (*s=='.') dot_pos=s++;
+ else if (*s=='/') dot_pos=NULL,name_pos=++s;
+ else s++;
+ }
+ if (!found_web) @<Make
+ |web_file_name|, |tex_file_name|, and |C_file_name|@>@;
+ else if (!found_change) @<Make |change_file_name| from |fname|@>@;
+ else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;
+ else @<Print usage error message and quit@>;
+ }
+ }
+ if (!found_web) @<Print usage error message and quit@>;
+ if (found_change<=0) strcpy(change_file_name,"/dev/null");
+}
+
+@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,
+otherwise we add |".w"|. If this file can't be opened, we prepare an
+|alt_web_file_name| by adding |"web"| after the dot.
+The other file names come from adding other things
+after the dot. We must check that there is enough room in
+|web_file_name| and the other arrays for the argument.
+
+@<Make |web_file_name|...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(web_file_name,"%s.w",*argv);
+ else {
+ strcpy(web_file_name,*argv);
+ *dot_pos=0; /* string now ends where the dot was */
+ }
+ sprintf(alt_web_file_name,"%s.web",*argv);
+ sprintf(tex_file_name,"%s.tex",name_pos); /* strip off directory name */
+ sprintf(idx_file_name,"%s.idx",name_pos);
+ sprintf(scn_file_name,"%s.scn",name_pos);
+ sprintf(C_file_name,"%s.c",name_pos);
+ found_web=1;
+}
+
+@ @<Make |change_file_name|...@>=
+{
+ if (strcmp(*argv,"-")==0) found_change=-1;
+ else {
+ if (s-*argv > max_file_name_length-4)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL)
+ sprintf(change_file_name,"%s.ch",*argv);
+ else strcpy(change_file_name,*argv);
+ found_change=1;
+ }
+}
+
+@ @<Override...@>=
+{
+ if (s-*argv > max_file_name_length-5)
+ @<Complain about argument length@>;
+ if (dot_pos==NULL) {
+ sprintf(tex_file_name,"%s.tex",*argv);
+ sprintf(idx_file_name,"%s.idx",*argv);
+ sprintf(scn_file_name,"%s.scn",*argv);
+ sprintf(C_file_name,"%s.c",*argv);
+ } else {
+ strcpy(tex_file_name,*argv);
+ strcpy(C_file_name,*argv);
+ if (flags['x']) { /* indexes will be generated */
+ *dot_pos=0;
+ sprintf(idx_file_name,"%s.idx",*argv);
+ sprintf(scn_file_name,"%s.scn",*argv);
+ }
+ }
+ found_out=1;
+}
+
+@ @<Handle flag...@>=
+{
+ if (**argv=='-') flag_change=0;
+ else flag_change=1;
+ for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)
+ flags[*dot_pos]=flag_change;
+}
+
+@ @<Print usage error message and quit@>=
+{
+if (program==ctangle)
+ fatal(
+"! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"
+ ,"");
+@.Usage:@>
+else fatal(
+"! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"
+ ,"");
+}
+
+@ @<Complain about arg...@>= fatal("! Filename too long\n", *argv);
+@.Filename too long@>
+
+@** Output. Here is the code that opens the output file:
+@^system dependencies@>
+
+@<Defin...@>=
+FILE *C_file; /* where output of \.{CTANGLE} goes */
+FILE *tex_file; /* where output of \.{CWEAVE} goes */
+FILE *idx_file; /* where index from \.{CWEAVE} goes */
+FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */
+FILE *active_file; /* currently active file for \.{CWEAVE} output */
+
+@ @<Scan arguments and open output files@>=
+scan_args();
+if (program==ctangle) {
+ if ((C_file=fopen(C_file_name,"w"))==NULL)
+ fatal("! Cannot open output file ", C_file_name);
+@.Cannot open output file@>
+}
+else {
+ if ((tex_file=fopen(tex_file_name,"w"))==NULL)
+ fatal("! Cannot open output file ", tex_file_name);
+}
+
+@ The |update_terminal| procedure is called when we want
+to make sure that everything we have output to the terminal so far has
+actually left the computer's internal buffers and been sent.
+@^system dependencies@>
+
+@d update_terminal fflush(stdout) /* empty the terminal output buffer */
+
+@ Terminal output uses |putchar| and |putc| when we have to
+translate from \.{CWEB}'s code into the external character code,
+and |printf| when we just want to print strings.
+Several macros make other kinds of output convenient.
+@^system dependencies@>
+@d new_line putchar('\n') @d putxchar putchar
+@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)
+@d C_printf(c,a) fprintf(C_file,c,a)
+@d C_putc(c) putc(c,C_file) /* isn't \CEE/ wonderfully consistent? */
+
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+
+@** Index.
diff --git a/Build/source/texk/web2c/cwebdir/ctang-bs.ch b/Build/source/texk/web2c/cwebdir/ctang-bs.ch
new file mode 100644
index 00000000000..634dc9acc83
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-bs.ch
@@ -0,0 +1,202 @@
+Changes for CTANGLE for MSDOS and Borland C++ 3.1 using the following
+options (and perhaps others):
+
+ -mc -w-pro -Ff=5000 -Z- -O-p
+
+The options -Z- and -O-p explicitly turn off optimizations that break
+the code. (See makefile.bs.)
+
+The main purpose of these changes is to support MSDOS with full-size arrays
+by using "huge" pointers.
+
+(This file contributed by Barry Schwartz, trashman@crud.mn.org, 28 Jun 94;
+ revised 24 Jul 94.)
+
+
+@x Section 1.
+The ``banner line'' defined here should be changed whenever \.{CTANGLE}
+is modified.
+
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+The ``banner line'' defined here should be changed whenever \.{CTANGLE}
+is modified.
+
+@d banner "This is CTANGLE (Version 3.64pc/big)\n"
+@z
+
+
+@x Section 4.
+@ The following parameters were sufficient in the original \.{TANGLE} to
+handle \TEX/,
+so they should be sufficient for most applications of \.{CTANGLE}.
+If you change |max_bytes|, |max_names| or |hash_size| you should also
+change them in the file |"common.w"|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; used in |"common.w"| */
+@d max_toks 270000 /* number of bytes in compressed \CEE/ code */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_texts 2500 /* number of replacement texts, must be less than 10240 */
+@d hash_size 353 /* should be prime; used in |"common.w"| */
+@d longest_name 1000 /* section names shouldn't be longer than this */
+@d stack_size 50 /* number of simultaneous levels of macro expansion */
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+@y
+@ The following parameters were sufficient in the original \.{TANGLE} to
+handle \TEX/,
+so they should be sufficient for most applications of \.{CTANGLE}.
+If you change |max_bytes|, |max_names| or |hash_size| you should also
+change them in the file |"common.w"|.
+
+(This is a modified version of \.{CTANGLE}, and in fact one of the parameters
+has been reduced in value. The parameter |max_toks|
+has been reduced from 270000 [which
+was sufficient to handle \TEX/] to
+170000, so that \.{CTANGLE}
+may be run on {\mc MSDOS}
+systems that are tight on memory. Consider, for
+instance, an 80286-based machine with several TSRs and drivers, trying
+to run \.{CTANGLE} from a makefile.)
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; used in |"common.w"| */
+@d max_toks 170000 /* number of bytes in compressed \CEE/ code */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_texts 2500 /* number of replacement texts, must be less than 10240 */
+@d hash_size 353 /* should be prime; used in |"common.w"| */
+@d longest_name 1000 /* section names shouldn't be longer than this */
+@d stack_size 50 /* number of simultaneous levels of macro expansion */
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+@z
+
+
+@x Section 9.
+@d chunk_marker 0
+
+@<Common code...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ } dummy;
+ char *equiv_or_xref; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char byte_mem[]; /* characters of names */
+extern char *byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char *byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@y
+@d chunk_marker 0
+
+@f huge extern
+
+@<Common code...@>=
+typedef struct name_info {
+ char huge* byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ } dummy;
+ union {
+ char *equiv_member;
+ char huge* xref_member;
+ } ptr_union; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char huge byte_mem[]; /* characters of names */
+extern char huge* byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char huge* byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@z
+
+
+@x Section 16.
+ eight_bits *tok_start; /* pointer into |tok_mem| */
+ sixteen_bits text_link; /* relates replacement texts */
+} text;
+typedef text *text_pointer;
+@y
+ eight_bits huge* tok_start; /* pointer into |tok_mem| */
+ sixteen_bits text_link; /* relates replacement texts */
+} text;
+typedef text *text_pointer;
+@z
+
+
+@x Section 17.
+eight_bits tok_mem[max_toks];
+eight_bits *tok_mem_end=tok_mem+max_toks-1;
+eight_bits *tok_ptr; /* first unused position in |tok_mem| */
+@y
+eight_bits huge tok_mem[max_toks];
+eight_bits huge* tok_mem_end;
+eight_bits huge* tok_ptr; /* first unused position in |tok_mem| */
+@z
+
+
+@x Section 18.
+text_info->tok_start=tok_ptr=tok_mem;
+text_ptr=text_info+1; text_ptr->tok_start=tok_mem;
+ /* this makes replacement text 0 of length zero */
+@y
+tok_mem_end=tok_mem+max_toks-1;
+text_info->tok_start=tok_ptr=tok_mem;
+text_ptr=text_info+1; text_ptr->tok_start=tok_mem;
+ /* this makes replacement text 0 of length zero */
+@z
+
+
+@x Section 19.
+@d equiv equiv_or_xref /* info corresponding to names */
+@y
+@d equiv ptr_union.equiv_member /* info corresponding to names */
+@z
+
+
+@x Section 27.
+ eight_bits *end_field; /* ending location of replacement text */
+ eight_bits *byte_field; /* present location within replacement text */
+@y
+ eight_bits huge* end_field; /* ending location of replacement text */
+ eight_bits huge* byte_field; /* present location within replacement text */
+@z
+
+
+@x Section 49.
+out_char(cur_char)
+eight_bits cur_char;
+{
+ char *j, *k; /* pointer into |byte_mem| */
+@y
+out_char(cur_char)
+eight_bits cur_char;
+{
+ char huge* j, huge* k; /* pointer into |byte_mem| */
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-man.ch b/Build/source/texk/web2c/cwebdir/ctang-man.ch
new file mode 100644
index 00000000000..12e9d3248ef
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-man.ch
@@ -0,0 +1,22 @@
+Change file to help make Appendix E of the full CWEB manual
+@x
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+@y
+\def\botofcontents{\vfill\titlefalse}
+\def\contentspagenumber{63}
+\def\title{APPENDIX E: CTANGLE}
+\let\K=\leftarrow
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-pc.ch b/Build/source/texk/web2c/cwebdir/ctang-pc.ch
new file mode 100644
index 00000000000..67f32fae0c2
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-pc.ch
@@ -0,0 +1,24 @@
+This is the change file for CWEB's CTANGLE under DOS
+(Contributed by Lee Wittenberg, March 1993)
+
+Changes necessary for compiling with Borland C/C++
+Use compilation switches -mc -w-pro -Ff=5000
+
+Note: The changes to section 4 are not necessary if using a compiler
+that allows >64K arrays. If you need lots of bytes and toks, try the
+alternate change files with -bs suffix instead of -pc.
+
+@x section 1
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+@d banner "This is CTANGLE (Version 3.64pc)\n"
+@z
+@x section 4
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; used in |"common.w"| */
+@d max_toks 270000 /* number of bytes in compressed \CEE/ code */
+@y (note that CWEAVE itself needs only about 42K toks)
+@d max_bytes (unsigned)60000 /* the number of bytes in identifiers,
+ index entries, and section names; used in |"common.w"| */
+@d max_toks (unsigned)60000 /* number of bytes in compressed \CEE/ code */
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-ql.ch b/Build/source/texk/web2c/cwebdir/ctang-ql.ch
new file mode 100644
index 00000000000..a0920243a97
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-ql.ch
@@ -0,0 +1,25 @@
+This is the change file for CWEB's CTANGLE under QDOS/SMSQ
+(Contributed by Robert H. Klein, September 1994)
+
+This change file is intended for use with C68 v4.13 (or later).
+compile with
+ex <dev_>cc;"-v -h -c -=500000 ctangle_c"
+
+
+@x
+\def\title{CTANGLE (Version 3.64)}
+@y
+\def\title{CTANGLE (QL Version 3.64)}
+@z
+
+@x section 1
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+@d banner "This is CTANGLE (QL Version 3.64)\n"
+@z
+
+@x
+@i common.h
+@y
+@i common_h
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-vms.ch b/Build/source/texk/web2c/cwebdir/ctang-vms.ch
new file mode 100644
index 00000000000..7e538abc27f
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-vms.ch
@@ -0,0 +1,35 @@
+This is the change file for CWEB's CTANGLE for VAX/VMS.
+
+created:
+ 01-FEB-1992 ST (Stephan Trebels <trebels@ams02.dnet.gwdg.de>)
+ > include ctype,stdio from textlibrary SYS$SHARE:VAXCDEF.TLB
+ > change banner line to include (VAX/VMS)
+ ? will someone make a CLD interface? (should be easy)
+
+(also modified by Don Knuth to keep version numbers uptodate)
+(these changes not necessary for initial bootstrapping)
+
+@x section 1 (01-FEB-1992 ST)
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+@d banner "This is CTANGLE (VAX/VMS Version 3.64)\n"
+@z
+
+@x section 6 (from common.h) (01-FEB-1992 ST)
+#include <stdio.h>
+@y
+#include stdio /* VMS searches Textlibraries faster */
+@z
+
+@x section 62 (01-FEB-1992 ST)
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+@y
+#include ctype /* definition of |isalpha|, |isdigit| and so on */
+ /* VMS searches text libraries faster */
+@z
+
+@x section 63 (01-FEB-1992 ST)
+@d isxalpha(c) ((c)=='_') /* non-alpha character allowed in identifier */
+@y
+@d isxalpha(c) ((c)=='_' || (c)=='$') /* non-alpha characters allowed in id */
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-w2c.ch b/Build/source/texk/web2c/cwebdir/ctang-w2c.ch
new file mode 100644
index 00000000000..0e71a5d5f73
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-w2c.ch
@@ -0,0 +1,375 @@
+% Kpathsea changes for CWEB by Wlodek Bzyl and Olaf Weber
+% Copyright 2002 Wlodek Bzyl and Olaf Weber
+% This file is in the Public Domain.
+
+@x l.27
+\def\title{CTANGLE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CTANGLE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+@y
+\def\title{CTANGLE (Version 3.64k)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CTANGLE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64k)}
+ \vfill}
+@z
+
+This change can not be applied when `tie' is used
+(TOC file can not be typeset).
+
+%@x l.48
+%\let\maybe=\iftrue
+%@y
+%\let\maybe=\iffalse % print only sections that change
+%@z
+
+
+Section 1.
+
+@x l.49
+The ``banner line'' defined here should be changed whenever \.{CTANGLE}
+is modified.
+
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+The ``banner line'' defined here should be changed whenever \.{CTANGLE}
+is modified.
+
+@d banner "This is CTANGLE, Version 3.64"
+@z
+
+
+Section 2.
+
+@x l.72
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
+
+Section 3.
+
+@x l.92
+int main (ac, av)
+int ac;
+char **av;
+@y
+int main P2C(int,ac, char**,av)
+@z
+
+@x l.100 - Add Web2C version to banner.
+ if (show_banner) printf(banner); /* print a ``banner line'' */
+@y
+ if (show_banner) {
+ printf("%s%s\n", banner, versionstring); /* print a ``banner line'' */
+ }
+@z
+
+Section 5.
+
+@x common.h l.30 - boolean comes from kpathsea.
+typedef short boolean;
+@y
+@z
+
+Section 6.
+
+@x l.36
+#include <stdio.h>
+@y
+#include <stdio.h>
+/* #include "cpascal.h" ??? */
+extern char *versionstring;
+#include <kpathsea/kpathsea.h>
+@z
+
+Section 9.
+
+@x common.h l.109
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@y
+/* looks up a string in the identifier table */
+extern name_pointer id_lookup P3H(char*,char*,char);
+/* finds section name */
+extern name_pointer section_lookup P3H(char*,char*,char);
+extern void print_section_name P1H(name_pointer);
+extern void sprint_section_name P2H(char*,name_pointer);
+@z
+
+Section 10.
+
+@x common.h l.123 - explicit types.
+extern history; /* indicates how bad this run was */
+extern err_print(); /* print error message and context */
+extern wrap_up(); /* indicate |history| and exit */
+extern void fatal(); /* issue error message and die */
+extern void overflow(); /* succumb because a table has overflowed */
+@y
+extern int history; /* indicates how bad this run was */
+extern void err_print P1H(char*); /* print error message and context */
+extern int wrap_up P1H(void); /* indicate |history| and exit */
+extern void fatal P2H(char*,char*); /* issue error message and die */
+extern void overflow P1H(char*); /* succumb because a table has overflowed */
+@z
+
+Section 11.
+
+@x common.h l.131 - max_file_name_length is way too small.
+@d max_file_name_length 60
+@y
+@d max_file_name_length 1024
+@z
+
+@x common.h l.138 - explicit types.
+extern include_depth; /* current level of nesting */
+@y
+extern int include_depth; /* current level of nesting */
+@z
+
+@x common.h l.148 - explicit types.
+extern line[]; /* number of current line in the stacked files */
+extern change_line; /* number of current line in change file */
+@y
+extern int line[]; /* number of current line in the stacked files */
+extern int change_line; /* number of current line in change file */
+@z
+
+@x common.h l.153 - explicit types.
+extern reset_input(); /* initialize to read the web file and change file */
+extern get_line(); /* inputs the next line */
+extern check_complete(); /* checks that all changes were picked up */
+@y
+extern void reset_input P1H(void); /* initialize to read the web file and change file */
+extern int get_line P1H(void); /* inputs the next line */
+extern void check_complete P1H(void); /* checks that all changes were picked up */
+@z
+
+Section 15.
+
+@x common.h l.192
+extern void common_init();
+@y
+extern void common_init P1H(void);
+@z
+
+Section 21.
+
+@x l.184
+int names_match(p,first,l)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+int l; /* length of identifier */
+@y
+int names_match P4C(name_pointer,p, char*,first, int,l, char,t)
+@z
+
+Section 22.
+
+@x l.200
+init_node(node)
+name_pointer node;
+@y
+init_node P1C(name_pointer,node)
+@z
+
+@x l.207
+init_p() {}
+@y
+init_p P2C(name_pointer,p, char,t) {}
+@z
+
+Section 26.
+
+@x l.262
+store_two_bytes(x)
+sixteen_bits x;
+@y
+store_two_bytes P1C(sixteen_bits,x)
+@z
+
+Section 30.
+
+@x l.338
+push_level(p) /* suspends the current level */
+name_pointer p;
+@y
+push_level P1C(name_pointer,p) /* suspends the current level */
+@z
+
+Section 31.
+
+@x l.357
+pop_level(flag) /* do this when |cur_byte| reaches |cur_end| */
+int flag; /* |flag==0| means we are in |output_defs| */
+@y
+pop_level P1C(int,flag) /* do this when |cur_byte| reaches |cur_end| */
+@z
+
+Section 33.
+
+@x l.393
+get_output() /* sends next token to |out_char| */
+@y
+get_output P1H(void) /* sends next token to |out_char| */
+@z
+
+Section 37.
+
+@x l.483
+flush_buffer() /* writes one line to output file */
+@y
+flush_buffer P1H(void) /* writes one line to output file */
+@z
+
+Section 41.
+
+@x l.534
+void phase_two();
+@y
+void phase_two P1H(void);
+@z
+
+Section 42.
+
+@x l.538
+phase_two () {
+@y
+phase_two P1H(void) {
+@z
+
+Section 46.
+
+@x l.603
+void output_defs();
+@y
+void output_defs P1H(void);
+@z
+
+Section 47.
+
+@x l.607
+output_defs()
+@y
+output_defs P1H(void)
+@z
+
+Section 48.
+
+@x l.649
+static void out_char();
+@y
+static void out_char P1H(eight_bits);
+@z
+
+Section 49.
+
+@x l.653
+out_char(cur_char)
+eight_bits cur_char;
+@y
+out_char P1C(eight_bits,cur_char)
+@z
+
+Section 58.
+
+@x l.815
+skip_ahead() /* skip to next control code */
+@y
+skip_ahead P1H(void) /* skip to next control code */
+@z
+
+Section 60.
+
+@x l.849
+int skip_comment(is_long_comment) /* skips over comments */
+boolean is_long_comment;
+@y
+int skip_comment P1C(boolean,is_long_comment) /* skips over comments */
+@z
+
+Section 62
+
+@x l.889 - add declaration of versionstring.
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+@y
+@z
+
+Section 63.
+
+@x l.902
+get_next() /* produces the next input token */
+@y
+get_next P1H(void) /* produces the next input token */
+@z
+
+Section 76.
+
+@x l.1201
+scan_repl(t) /* creates a replacement text */
+eight_bits t;
+@y
+scan_repl P1C(eight_bits,t) /* creates a replacement text */
+@z
+
+Section 83.
+
+@x l.1359
+scan_section()
+@y
+scan_section P1H(void)
+@z
+
+Section 90.
+
+@x l.1458
+void phase_one();
+@y
+void phase_one P1H(void);
+@z
+
+Section 91.
+
+@x l.1462
+phase_one() {
+@y
+phase_one P1H(void) {
+@z
+
+Section 92.
+
+@x l.1476
+void skip_limbo();
+@y
+void skip_limbo P1H(void);
+@z
+
+Section 93.
+
+@x l.1480
+skip_limbo()
+@y
+skip_limbo P1H(void)
+@z
+
+Section 95.
+
+@x l.1535
+print_stats() {
+@y
+print_stats P1H(void) {
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctang-w32.ch b/Build/source/texk/web2c/cwebdir/ctang-w32.ch
new file mode 100644
index 00000000000..523985ce3da
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctang-w32.ch
@@ -0,0 +1,66 @@
+This is the change file for CWEB's CTANGLE under Win32
+(Contributed by Fabrice Popineau, February 2002)
+
+Changes necessary for compiling with Borland C/C++
+
+@x section 1
+@d banner "This is CTANGLE (Version 3.64)\n"
+@y
+@d banner "This is CTANGLE (Version 3.64win32)\n"
+@z
+
+@x
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
+
+@x
+int names_match(p,first,l)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+@y
+int __cdecl names_match(p,first,l)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+@z
+
+@x
+void
+init_node(node)
+name_pointer node;
+{
+ node->equiv=(char *)text_info;
+}
+void
+init_p() {}
+@y
+void
+init_node(node)
+name_pointer node;
+{
+ node->equiv=(char *)text_info;
+}
+void __cdecl
+init_p() {}
+@z
+
+@x
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+@y
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+#include <string.h>
+@z
diff --git a/Build/source/texk/web2c/cwebdir/ctangle.c b/Build/source/texk/web2c/cwebdir/ctangle.c
new file mode 100644
index 00000000000..01fa7c407cd
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctangle.c
@@ -0,0 +1,1566 @@
+/*1:*/
+#line 64 "ctangle.w"
+
+/*6:*/
+#line 35 "common.h"
+
+#include <stdio.h>
+
+/*:6*//*62:*/
+#line 888 "ctangle.w"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+/*:62*/
+#line 65 "ctangle.w"
+
+#define banner "This is CTANGLE (Version 3.64)\n" \
+
+#define max_bytes 90000 \
+
+#define max_toks 270000
+#define max_names 4000 \
+
+#define max_texts 2500
+#define hash_size 353
+#define longest_name 10000
+#define stack_size 50
+#define buf_size 100 \
+
+#define ctangle 0
+#define cweave 1 \
+
+#define and_and 04
+#define lt_lt 020
+#define gt_gt 021
+#define plus_plus 013
+#define minus_minus 01
+#define minus_gt 031
+#define not_eq 032
+#define lt_eq 034
+#define gt_eq 035
+#define eq_eq 036
+#define or_or 037
+#define dot_dot_dot 016
+#define colon_colon 06
+#define period_ast 026
+#define minus_gt_ast 027 \
+
+#define xisalpha(c) (isalpha(c) &&((eight_bits) c<0200) )
+#define xisdigit(c) (isdigit(c) &&((eight_bits) c<0200) )
+#define xisspace(c) (isspace(c) &&((eight_bits) c<0200) )
+#define xislower(c) (islower(c) &&((eight_bits) c<0200) )
+#define xisupper(c) (isupper(c) &&((eight_bits) c<0200) )
+#define xisxdigit(c) (isxdigit(c) &&((eight_bits) c<0200) ) \
+
+#define length(c) (c+1) ->byte_start-(c) ->byte_start
+#define print_id(c) term_write((c) ->byte_start,length((c) ) )
+#define llink link
+#define rlink dummy.Rlink
+#define root name_dir->rlink \
+
+#define chunk_marker 0 \
+
+#define spotless 0
+#define harmless_message 1
+#define error_message 2
+#define fatal_message 3
+#define mark_harmless {if(history==spotless) history= harmless_message;}
+#define mark_error history= error_message
+#define confusion(s) fatal("! This can't happen: ",s) \
+
+#define max_file_name_length 60
+#define cur_file file[include_depth]
+#define cur_file_name file_name[include_depth]
+#define web_file_name file_name[0]
+#define cur_line line[include_depth] \
+
+#define show_banner flags['b']
+#define show_progress flags['p']
+#define show_happiness flags['h'] \
+
+#define update_terminal fflush(stdout)
+#define new_line putchar('\n')
+#define putxchar putchar
+#define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout)
+#define C_printf(c,a) fprintf(C_file,c,a)
+#define C_putc(c) putc(c,C_file) \
+
+#define equiv equiv_or_xref \
+
+#define section_flag max_texts \
+
+#define string 02
+#define join 0177
+#define output_defs_flag (2*024000-1) \
+
+#define cur_end cur_state.end_field
+#define cur_byte cur_state.byte_field
+#define cur_name cur_state.name_field
+#define cur_repl cur_state.repl_field
+#define cur_section cur_state.section_field \
+
+#define section_number 0201
+#define identifier 0202 \
+
+#define normal 0
+#define num_or_id 1
+#define post_slash 2
+#define unbreakable 3
+#define verbatim 4 \
+
+#define max_files 256
+#define translit_length 10 \
+
+#define ignore 0
+#define ord 0302
+#define control_text 0303
+#define translit_code 0304
+#define output_defs_code 0305
+#define format_code 0306
+#define definition 0307
+#define begin_C 0310
+#define section_name 0311
+#define new_section 0312 \
+
+#define constant 03 \
+
+#define isxalpha(c) ((c) =='_'||(c) =='$') \
+
+#define ishigh(c) ((unsigned char) (c) > 0177) \
+ \
+
+#define compress(c) if(loc++<=limit) return(c) \
+
+#define macro 0
+#define app_repl(c) {if(tok_ptr==tok_mem_end) overflow("token") ;*tok_ptr++= c;} \
+
+
+#line 66 "ctangle.w"
+
+/*5:*/
+#line 29 "common.h"
+
+typedef short boolean;
+typedef char unsigned eight_bits;
+extern boolean program;
+extern int phase;
+
+/*:5*//*7:*/
+#line 57 "common.h"
+
+char section_text[longest_name+1];
+char*section_text_end= section_text+longest_name;
+char*id_first;
+char*id_loc;
+
+/*:7*//*8:*/
+#line 72 "common.h"
+
+extern char buffer[];
+extern char*buffer_end;
+extern char*loc;
+extern char*limit;
+
+/*:8*//*9:*/
+#line 87 "common.h"
+
+typedef struct name_info{
+char*byte_start;
+struct name_info*link;
+union{
+struct name_info*Rlink;
+
+char Ilk;
+}dummy;
+char*equiv_or_xref;
+}name_info;
+typedef name_info*name_pointer;
+typedef name_pointer*hash_pointer;
+extern char byte_mem[];
+extern char*byte_mem_end;
+extern name_info name_dir[];
+extern name_pointer name_dir_end;
+extern name_pointer name_ptr;
+extern char*byte_ptr;
+extern name_pointer hash[];
+extern hash_pointer hash_end;
+extern hash_pointer h;
+extern name_pointer id_lookup();
+extern name_pointer section_lookup();
+extern void print_section_name(),sprint_section_name();
+
+/*:9*//*10:*/
+#line 122 "common.h"
+
+extern history;
+extern err_print();
+extern wrap_up();
+extern void fatal();
+extern void overflow();
+
+/*:10*//*11:*/
+#line 137 "common.h"
+
+extern include_depth;
+extern FILE*file[];
+extern FILE*change_file;
+extern char C_file_name[];
+extern char tex_file_name[];
+extern char idx_file_name[];
+extern char scn_file_name[];
+extern char file_name[][max_file_name_length];
+
+extern char change_file_name[];
+extern line[];
+extern change_line;
+extern boolean input_has_ended;
+extern boolean changing;
+extern boolean web_file_open;
+extern reset_input();
+extern get_line();
+extern check_complete();
+
+/*:11*//*12:*/
+#line 158 "common.h"
+
+typedef unsigned short sixteen_bits;
+extern sixteen_bits section_count;
+extern boolean changed_section[];
+extern boolean change_pending;
+extern boolean print_where;
+
+/*:12*//*13:*/
+#line 170 "common.h"
+
+extern int argc;
+extern char**argv;
+extern boolean flags[];
+
+/*:13*//*14:*/
+#line 182 "common.h"
+
+extern FILE*C_file;
+extern FILE*tex_file;
+extern FILE*idx_file;
+extern FILE*scn_file;
+extern FILE*active_file;
+
+/*:14*//*15:*/
+#line 191 "common.h"
+
+extern void common_init();
+#line 128 "ctangle.w"
+
+/*:15*/
+#line 67 "ctangle.w"
+
+/*16:*/
+#line 152 "ctangle.w"
+
+typedef struct{
+eight_bits*tok_start;
+sixteen_bits text_link;
+}text;
+typedef text*text_pointer;
+
+/*:16*//*27:*/
+#line 296 "ctangle.w"
+
+typedef struct{
+eight_bits*end_field;
+eight_bits*byte_field;
+name_pointer name_field;
+text_pointer repl_field;
+sixteen_bits section_field;
+}output_state;
+typedef output_state*stack_pointer;
+
+/*:27*/
+#line 68 "ctangle.w"
+
+/*17:*/
+#line 159 "ctangle.w"
+
+text text_info[max_texts];
+text_pointer text_info_end= text_info+max_texts-1;
+text_pointer text_ptr;
+eight_bits tok_mem[max_toks];
+eight_bits*tok_mem_end= tok_mem+max_toks-1;
+eight_bits*tok_ptr;
+
+/*:17*//*23:*/
+#line 227 "ctangle.w"
+
+text_pointer last_unnamed;
+
+/*:23*//*28:*/
+#line 312 "ctangle.w"
+
+output_state cur_state;
+
+output_state stack[stack_size+1];
+stack_pointer stack_ptr;
+stack_pointer stack_end= stack+stack_size;
+
+/*:28*//*32:*/
+#line 384 "ctangle.w"
+
+int cur_val;
+
+/*:32*//*36:*/
+#line 473 "ctangle.w"
+
+eight_bits out_state;
+boolean protect;
+
+/*:36*//*38:*/
+#line 502 "ctangle.w"
+
+name_pointer output_files[max_files];
+name_pointer*cur_out_file,*end_output_files,*an_output_file;
+char cur_section_name_char;
+char output_file_name[longest_name];
+
+/*:38*//*45:*/
+#line 599 "ctangle.w"
+
+boolean output_defs_seen= 0;
+
+/*:45*//*51:*/
+#line 710 "ctangle.w"
+
+char translit[128][translit_length];
+
+/*:51*//*56:*/
+#line 789 "ctangle.w"
+
+eight_bits ccode[256];
+
+/*:56*//*59:*/
+#line 845 "ctangle.w"
+
+boolean comment_continues= 0;
+
+/*:59*//*61:*/
+#line 884 "ctangle.w"
+
+name_pointer cur_section_name;
+int no_where;
+
+/*:61*//*75:*/
+#line 1195 "ctangle.w"
+
+text_pointer cur_text;
+eight_bits next_control;
+
+/*:75*//*82:*/
+#line 1350 "ctangle.w"
+
+extern sixteen_bits section_count;
+
+/*:82*/
+#line 69 "ctangle.w"
+
+/*2:*/
+#line 77 "ctangle.w"
+
+extern int strlen();
+extern int strcmp();
+extern char*strcpy();
+extern int strncmp();
+extern char*strncpy();
+
+/*:2*//*41:*/
+#line 533 "ctangle.w"
+
+void phase_two();
+
+/*:41*//*46:*/
+#line 602 "ctangle.w"
+
+void output_defs();
+
+/*:46*//*48:*/
+#line 648 "ctangle.w"
+
+static void out_char();
+
+/*:48*//*90:*/
+#line 1457 "ctangle.w"
+
+void phase_one();
+
+/*:90*//*92:*/
+#line 1475 "ctangle.w"
+
+void skip_limbo();
+
+/*:92*/
+#line 70 "ctangle.w"
+
+
+/*:1*//*3:*/
+#line 91 "ctangle.w"
+
+int main(ac,av)
+int ac;
+char**av;
+{
+argc= ac;argv= av;
+program= ctangle;
+/*18:*/
+#line 167 "ctangle.w"
+
+text_info->tok_start= tok_ptr= tok_mem;
+text_ptr= text_info+1;text_ptr->tok_start= tok_mem;
+
+
+/*:18*//*20:*/
+#line 177 "ctangle.w"
+
+name_dir->equiv= (char*)text_info;
+
+/*:20*//*24:*/
+#line 230 "ctangle.w"
+last_unnamed= text_info;text_info->text_link= 0;
+
+/*:24*//*39:*/
+#line 512 "ctangle.w"
+
+cur_out_file= end_output_files= output_files+max_files;
+
+/*:39*//*52:*/
+#line 713 "ctangle.w"
+
+{
+int i;
+for(i= 0;i<128;i++)sprintf(translit[i],"X%02X",(unsigned)(128+i));
+}
+
+/*:52*//*57:*/
+#line 792 "ctangle.w"
+{
+int c;
+for(c= 0;c<256;c++)ccode[c]= ignore;
+ccode[' ']= ccode['\t']= ccode['\n']= ccode['\v']= ccode['\r']= ccode['\f']
+= ccode['*']= new_section;
+ccode['@']= '@';ccode['=']= string;
+ccode['d']= ccode['D']= definition;
+ccode['f']= ccode['F']= ccode['s']= ccode['S']= format_code;
+ccode['c']= ccode['C']= ccode['p']= ccode['P']= begin_C;
+ccode['^']= ccode[':']= ccode['.']= ccode['t']= ccode['T']=
+ccode['q']= ccode['Q']= control_text;
+ccode['h']= ccode['H']= output_defs_code;
+ccode['l']= ccode['L']= translit_code;
+ccode['&']= join;
+ccode['<']= ccode['(']= section_name;
+ccode['\'']= ord;
+}
+
+/*:57*//*71:*/
+#line 1116 "ctangle.w"
+section_text[0]= ' ';
+
+/*:71*/
+#line 98 "ctangle.w"
+;
+common_init();
+if(show_banner)printf(banner);
+phase_one();
+phase_two();
+return wrap_up();
+}
+
+/*:3*//*21:*/
+#line 183 "ctangle.w"
+
+int names_match(p,first,l)
+name_pointer p;
+char*first;
+int l;
+{
+if(length(p)!=l)return 0;
+return!strncmp(first,p->byte_start,l);
+}
+
+/*:21*//*22:*/
+#line 198 "ctangle.w"
+
+void
+init_node(node)
+name_pointer node;
+{
+node->equiv= (char*)text_info;
+}
+void
+init_p(){}
+
+/*:22*//*26:*/
+#line 260 "ctangle.w"
+
+void
+store_two_bytes(x)
+sixteen_bits x;
+{
+if(tok_ptr+2> tok_mem_end)overflow("token");
+*tok_ptr++= x>>8;
+*tok_ptr++= x&0377;
+}
+
+/*:26*//*30:*/
+#line 336 "ctangle.w"
+
+void
+push_level(p)
+name_pointer p;
+{
+if(stack_ptr==stack_end)overflow("stack");
+*stack_ptr= cur_state;
+stack_ptr++;
+if(p!=NULL){
+cur_name= p;cur_repl= (text_pointer)p->equiv;
+cur_byte= cur_repl->tok_start;cur_end= (cur_repl+1)->tok_start;
+cur_section= 0;
+}
+}
+
+/*:30*//*31:*/
+#line 355 "ctangle.w"
+
+void
+pop_level(flag)
+int flag;
+{
+if(flag&&cur_repl->text_link<section_flag){
+cur_repl= cur_repl->text_link+text_info;
+cur_byte= cur_repl->tok_start;cur_end= (cur_repl+1)->tok_start;
+return;
+}
+stack_ptr--;
+if(stack_ptr> stack)cur_state= *stack_ptr;
+}
+
+/*:31*//*33:*/
+#line 391 "ctangle.w"
+
+void
+get_output()
+{
+sixteen_bits a;
+restart:if(stack_ptr==stack)return;
+if(cur_byte==cur_end){
+cur_val= -((int)cur_section);
+pop_level(1);
+if(cur_val==0)goto restart;
+out_char(section_number);return;
+}
+a= *cur_byte++;
+if(out_state==verbatim&&a!=string&&a!=constant&&a!='\n')
+C_putc(a);
+else if(a<0200)out_char(a);
+else{
+a= (a-0200)*0400+*cur_byte++;
+switch(a/024000){
+case 0:cur_val= a;out_char(identifier);break;
+case 1:if(a==output_defs_flag)output_defs();
+else/*34:*/
+#line 423 "ctangle.w"
+
+{
+a-= 024000;
+if((a+name_dir)->equiv!=(char*)text_info)push_level(a+name_dir);
+else if(a!=0){
+printf("\n! Not present: <");
+print_section_name(a+name_dir);err_print(">");
+
+}
+goto restart;
+}
+
+/*:34*/
+#line 412 "ctangle.w"
+;
+break;
+default:cur_val= a-050000;if(cur_val> 0)cur_section= cur_val;
+out_char(section_number);
+}
+}
+}
+
+/*:33*//*37:*/
+#line 481 "ctangle.w"
+
+void
+flush_buffer()
+{
+C_putc('\n');
+if(cur_line%100==0&&show_progress){
+printf(".");
+if(cur_line%500==0)printf("%d",cur_line);
+update_terminal;
+}
+cur_line++;
+}
+
+/*:37*//*42:*/
+#line 536 "ctangle.w"
+
+void
+phase_two(){
+web_file_open= 0;
+cur_line= 1;
+/*29:*/
+#line 325 "ctangle.w"
+
+stack_ptr= stack+1;cur_name= name_dir;cur_repl= text_info->text_link+text_info;
+cur_byte= cur_repl->tok_start;cur_end= (cur_repl+1)->tok_start;cur_section= 0;
+
+/*:29*/
+#line 541 "ctangle.w"
+;
+/*44:*/
+#line 595 "ctangle.w"
+
+if(!output_defs_seen)
+output_defs();
+
+/*:44*/
+#line 542 "ctangle.w"
+;
+if(text_info->text_link==0&&cur_out_file==end_output_files){
+printf("\n! No program text was specified.");mark_harmless;
+
+}
+else{
+if(cur_out_file==end_output_files){
+if(show_progress)
+printf("\nWriting the output file (%s):",C_file_name);
+}
+else{
+if(show_progress){
+printf("\nWriting the output files:");
+
+printf(" (%s)",C_file_name);
+update_terminal;
+}
+if(text_info->text_link==0)goto writeloop;
+}
+while(stack_ptr> stack)get_output();
+flush_buffer();
+writeloop:/*43:*/
+#line 572 "ctangle.w"
+
+for(an_output_file= end_output_files;an_output_file> cur_out_file;){
+an_output_file--;
+sprint_section_name(output_file_name,*an_output_file);
+fclose(C_file);
+C_file= fopen(output_file_name,"w");
+if(C_file==0)fatal("! Cannot open output file:",output_file_name);
+
+printf("\n(%s)",output_file_name);update_terminal;
+cur_line= 1;
+stack_ptr= stack+1;
+cur_name= (*an_output_file);
+cur_repl= (text_pointer)cur_name->equiv;
+cur_byte= cur_repl->tok_start;
+cur_end= (cur_repl+1)->tok_start;
+while(stack_ptr> stack)get_output();
+flush_buffer();
+}
+
+/*:43*/
+#line 563 "ctangle.w"
+;
+if(show_happiness)printf("\nDone.");
+}
+}
+
+/*:42*//*47:*/
+#line 605 "ctangle.w"
+
+void
+output_defs()
+{
+sixteen_bits a;
+push_level(NULL);
+for(cur_text= text_info+1;cur_text<text_ptr;cur_text++)
+if(cur_text->text_link==0){
+cur_byte= cur_text->tok_start;
+cur_end= (cur_text+1)->tok_start;
+C_printf("%s","#define ");
+out_state= normal;
+protect= 1;
+while(cur_byte<cur_end){
+a= *cur_byte++;
+if(cur_byte==cur_end&&a=='\n')break;
+if(out_state==verbatim&&a!=string&&a!=constant&&a!='\n')
+C_putc(a);
+
+else if(a<0200)out_char(a);
+else{
+a= (a-0200)*0400+*cur_byte++;
+if(a<024000){
+cur_val= a;out_char(identifier);
+}
+else if(a<050000){confusion("macro defs have strange char");}
+else{
+cur_val= a-050000;cur_section= cur_val;out_char(section_number);
+}
+
+}
+}
+protect= 0;
+flush_buffer();
+}
+pop_level(0);
+}
+
+/*:47*//*49:*/
+#line 651 "ctangle.w"
+
+static void
+out_char(cur_char)
+eight_bits cur_char;
+{
+char*j,*k;
+restart:
+switch(cur_char){
+case'\n':if(protect&&out_state!=verbatim)C_putc(' ');
+if(protect||out_state==verbatim)C_putc('\\');
+flush_buffer();if(out_state!=verbatim)out_state= normal;break;
+/*53:*/
+#line 719 "ctangle.w"
+
+case identifier:
+if(out_state==num_or_id)C_putc(' ');
+j= (cur_val+name_dir)->byte_start;
+k= (cur_val+name_dir+1)->byte_start;
+while(j<k){
+if((unsigned char)(*j)<0200)C_putc(*j);
+
+else C_printf("%s",translit[(unsigned char)(*j)-0200]);
+j++;
+}
+out_state= num_or_id;break;
+
+/*:53*/
+#line 662 "ctangle.w"
+;
+/*54:*/
+#line 732 "ctangle.w"
+
+case section_number:
+if(cur_val> 0)C_printf("/*%d:*/",cur_val);
+else if(cur_val<0)C_printf("/*:%d*/",-cur_val);
+else if(protect){
+cur_byte+= 4;
+cur_char= '\n';
+goto restart;
+}else{
+sixteen_bits a;
+a= 0400**cur_byte++;
+a+= *cur_byte++;
+C_printf("\n#line %d \"",a);
+
+cur_val= *cur_byte++;
+cur_val= 0400*(cur_val-0200)+*cur_byte++;
+for(j= (cur_val+name_dir)->byte_start,k= (cur_val+name_dir+1)->byte_start;
+j<k;j++){
+if(*j=='\\'||*j=='"')C_putc('\\');
+C_putc(*j);
+}
+C_printf("%s","\"\n");
+}
+break;
+
+/*:54*/
+#line 663 "ctangle.w"
+;
+/*50:*/
+#line 681 "ctangle.w"
+
+case plus_plus:C_putc('+');C_putc('+');out_state= normal;break;
+case minus_minus:C_putc('-');C_putc('-');out_state= normal;break;
+case minus_gt:C_putc('-');C_putc('>');out_state= normal;break;
+case gt_gt:C_putc('>');C_putc('>');out_state= normal;break;
+case eq_eq:C_putc('=');C_putc('=');out_state= normal;break;
+case lt_lt:C_putc('<');C_putc('<');out_state= normal;break;
+case gt_eq:C_putc('>');C_putc('=');out_state= normal;break;
+case lt_eq:C_putc('<');C_putc('=');out_state= normal;break;
+case not_eq:C_putc('!');C_putc('=');out_state= normal;break;
+case and_and:C_putc('&');C_putc('&');out_state= normal;break;
+case or_or:C_putc('|');C_putc('|');out_state= normal;break;
+case dot_dot_dot:C_putc('.');C_putc('.');C_putc('.');out_state= normal;
+break;
+case colon_colon:C_putc(':');C_putc(':');out_state= normal;break;
+case period_ast:C_putc('.');C_putc('*');out_state= normal;break;
+case minus_gt_ast:C_putc('-');C_putc('>');C_putc('*');out_state= normal;
+break;
+
+/*:50*/
+#line 664 "ctangle.w"
+;
+case'=':case'>':C_putc(cur_char);C_putc(' ');
+out_state= normal;break;
+case join:out_state= unbreakable;break;
+case constant:if(out_state==verbatim){
+out_state= num_or_id;break;
+}
+if(out_state==num_or_id)C_putc(' ');out_state= verbatim;break;
+case string:if(out_state==verbatim)out_state= normal;
+else out_state= verbatim;break;
+case'/':C_putc('/');out_state= post_slash;break;
+case'*':if(out_state==post_slash)C_putc(' ');
+
+default:C_putc(cur_char);out_state= normal;break;
+}
+}
+
+/*:49*//*58:*/
+#line 813 "ctangle.w"
+
+eight_bits
+skip_ahead()
+{
+eight_bits c;
+while(1){
+if(loc> limit&&(get_line()==0))return(new_section);
+*(limit+1)= '@';
+while(*loc!='@')loc++;
+if(loc<=limit){
+loc++;c= ccode[(eight_bits)*loc];loc++;
+if(c!=ignore||*(loc-1)=='>')return(c);
+}
+}
+}
+
+/*:58*//*60:*/
+#line 848 "ctangle.w"
+
+int skip_comment(is_long_comment)
+boolean is_long_comment;
+{
+char c;
+while(1){
+if(loc> limit){
+if(is_long_comment){
+if(get_line())return(comment_continues= 1);
+else{
+err_print("! Input ended in mid-comment");
+
+return(comment_continues= 0);
+}
+}
+else return(comment_continues= 0);
+}
+c= *(loc++);
+if(is_long_comment&&c=='*'&&*loc=='/'){
+loc++;return(comment_continues= 0);
+}
+if(c=='@'){
+if(ccode[(eight_bits)*loc]==new_section){
+err_print("! Section name ended in mid-comment");loc--;
+
+return(comment_continues= 0);
+}
+else loc++;
+}
+}
+}
+
+/*:60*//*63:*/
+#line 900 "ctangle.w"
+
+eight_bits
+get_next()
+{
+static int preprocessing= 0;
+eight_bits c;
+while(1){
+if(loc> limit){
+if(preprocessing&&*(limit-1)!='\\')preprocessing= 0;
+if(get_line()==0)return(new_section);
+else if(print_where&&!no_where){
+print_where= 0;
+/*77:*/
+#line 1225 "ctangle.w"
+
+store_two_bytes(0150000);
+if(changing)id_first= change_file_name;
+else id_first= cur_file_name;
+id_loc= id_first+strlen(id_first);
+if(changing)store_two_bytes((sixteen_bits)change_line);
+else store_two_bytes((sixteen_bits)cur_line);
+{int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200);
+app_repl(a%0400);}
+
+/*:77*/
+#line 912 "ctangle.w"
+;
+}
+else return('\n');
+}
+c= *loc;
+if(comment_continues||(c=='/'&&(*(loc+1)=='*'||*(loc+1)=='/'))){
+skip_comment(comment_continues||*(loc+1)=='*');
+
+if(comment_continues)return('\n');
+else continue;
+}
+loc++;
+if(xisdigit(c)||c=='.')/*66:*/
+#line 978 "ctangle.w"
+{
+id_first= loc-1;
+if(*id_first=='.'&&!xisdigit(*loc))goto mistake;
+if(*id_first=='0'){
+if(*loc=='x'||*loc=='X'){
+loc++;while(xisxdigit(*loc))loc++;goto found;
+}
+}
+while(xisdigit(*loc))loc++;
+if(*loc=='.'){
+loc++;
+while(xisdigit(*loc))loc++;
+}
+if(*loc=='e'||*loc=='E'){
+if(*++loc=='+'||*loc=='-')loc++;
+while(xisdigit(*loc))loc++;
+}
+found:while(*loc=='u'||*loc=='U'||*loc=='l'||*loc=='L'
+||*loc=='f'||*loc=='F')loc++;
+id_loc= loc;
+return(constant);
+}
+
+/*:66*/
+#line 924 "ctangle.w"
+
+else if(c=='\''||c=='"'||(c=='L'&&(*loc=='\''||*loc=='"')))
+/*67:*/
+#line 1006 "ctangle.w"
+{
+char delim= c;
+id_first= section_text+1;
+id_loc= section_text;*++id_loc= delim;
+if(delim=='L'){
+delim= *loc++;*++id_loc= delim;
+}
+while(1){
+if(loc>=limit){
+if(*(limit-1)!='\\'){
+err_print("! String didn't end");loc= limit;break;
+
+}
+if(get_line()==0){
+err_print("! Input ended in middle of string");loc= buffer;break;
+
+}
+else if(++id_loc<=section_text_end)*id_loc= '\n';
+
+}
+if((c= *loc++)==delim){
+if(++id_loc<=section_text_end)*id_loc= c;
+break;
+}
+if(c=='\\'){
+if(loc>=limit)continue;
+if(++id_loc<=section_text_end)*id_loc= '\\';
+c= *loc++;
+}
+if(++id_loc<=section_text_end)*id_loc= c;
+}
+if(id_loc>=section_text_end){
+printf("\n! String too long: ");
+
+term_write(section_text+1,25);
+err_print("...");
+}
+id_loc++;
+return(string);
+}
+
+/*:67*/
+#line 926 "ctangle.w"
+
+else if(isalpha(c)||isxalpha(c)||ishigh(c))
+/*65:*/
+#line 972 "ctangle.w"
+{
+id_first= --loc;
+while(isalpha(*++loc)||isdigit(*loc)||isxalpha(*loc)||ishigh(*loc));
+id_loc= loc;return(identifier);
+}
+
+/*:65*/
+#line 928 "ctangle.w"
+
+else if(c=='@')/*68:*/
+#line 1050 "ctangle.w"
+{
+c= ccode[(eight_bits)*loc++];
+switch(c){
+case ignore:continue;
+case translit_code:err_print("! Use @l in limbo only");continue;
+
+case control_text:while((c= skip_ahead())=='@');
+
+if(*(loc-1)!='>')
+err_print("! Double @ should be used in control text");
+
+continue;
+case section_name:
+cur_section_name_char= *(loc-1);
+/*70:*/
+#line 1098 "ctangle.w"
+{
+char*k;
+/*72:*/
+#line 1118 "ctangle.w"
+
+k= section_text;
+while(1){
+if(loc> limit&&get_line()==0){
+err_print("! Input ended in section name");
+
+loc= buffer+1;break;
+}
+c= *loc;
+/*73:*/
+#line 1142 "ctangle.w"
+
+if(c=='@'){
+c= *(loc+1);
+if(c=='>'){
+loc+= 2;break;
+}
+if(ccode[(eight_bits)c]==new_section){
+err_print("! Section name didn't end");break;
+
+}
+if(ccode[(eight_bits)c]==section_name){
+err_print("! Nesting of section names not allowed");break;
+
+}
+*(++k)= '@';loc++;
+}
+
+/*:73*/
+#line 1127 "ctangle.w"
+;
+loc++;if(k<section_text_end)k++;
+if(xisspace(c)){
+c= ' ';if(*(k-1)==' ')k--;
+}
+*k= c;
+}
+if(k>=section_text_end){
+printf("\n! Section name too long: ");
+
+term_write(section_text+1,25);
+printf("...");mark_harmless;
+}
+if(*k==' '&&k> section_text)k--;
+
+/*:72*/
+#line 1100 "ctangle.w"
+;
+if(k-section_text> 3&&strncmp(k-2,"...",3)==0)
+cur_section_name= section_lookup(section_text+1,k-3,1);
+else cur_section_name= section_lookup(section_text+1,k,0);
+if(cur_section_name_char=='(')
+/*40:*/
+#line 516 "ctangle.w"
+
+{
+for(an_output_file= cur_out_file;
+an_output_file<end_output_files;an_output_file++)
+if(*an_output_file==cur_section_name)break;
+if(an_output_file==end_output_files){
+if(cur_out_file> output_files)
+*--cur_out_file= cur_section_name;
+else{
+overflow("output files");
+}
+}
+}
+
+/*:40*/
+#line 1106 "ctangle.w"
+;
+return(section_name);
+}
+
+/*:70*/
+#line 1064 "ctangle.w"
+;
+case string:/*74:*/
+#line 1164 "ctangle.w"
+{
+id_first= loc++;*(limit+1)= '@';*(limit+2)= '>';
+while(*loc!='@'||*(loc+1)!='>')loc++;
+if(loc>=limit)err_print("! Verbatim string didn't end");
+
+id_loc= loc;loc+= 2;
+return(string);
+}
+
+/*:74*/
+#line 1065 "ctangle.w"
+;
+case ord:/*69:*/
+#line 1077 "ctangle.w"
+
+id_first= loc;
+if(*loc=='\\'){
+if(*++loc=='\'')loc++;
+}
+while(*loc!='\''){
+if(*loc=='@'){
+if(*(loc+1)!='@')
+err_print("! Double @ should be used in ASCII constant");
+
+else loc++;
+}
+loc++;
+if(loc> limit){
+err_print("! String didn't end");loc= limit-1;break;
+
+}
+}
+loc++;
+return(ord);
+
+/*:69*/
+#line 1066 "ctangle.w"
+;
+default:return(c);
+}
+}
+
+/*:68*/
+#line 929 "ctangle.w"
+
+else if(xisspace(c)){
+if(!preprocessing||loc> limit)continue;
+
+else return(' ');
+}
+else if(c=='#'&&loc==buffer+1)preprocessing= 1;
+mistake:/*64:*/
+#line 950 "ctangle.w"
+
+switch(c){
+case'+':if(*loc=='+')compress(plus_plus);break;
+case'-':if(*loc=='-'){compress(minus_minus);}
+else if(*loc=='>')if(*(loc+1)=='*'){loc++;compress(minus_gt_ast);}
+else compress(minus_gt);break;
+case'.':if(*loc=='*'){compress(period_ast);}
+else if(*loc=='.'&&*(loc+1)=='.'){
+loc++;compress(dot_dot_dot);
+}
+break;
+case':':if(*loc==':')compress(colon_colon);break;
+case'=':if(*loc=='=')compress(eq_eq);break;
+case'>':if(*loc=='='){compress(gt_eq);}
+else if(*loc=='>')compress(gt_gt);break;
+case'<':if(*loc=='='){compress(lt_eq);}
+else if(*loc=='<')compress(lt_lt);break;
+case'&':if(*loc=='&')compress(and_and);break;
+case'|':if(*loc=='|')compress(or_or);break;
+case'!':if(*loc=='=')compress(not_eq);break;
+}
+
+/*:64*/
+#line 936 "ctangle.w"
+
+return(c);
+}
+}
+
+/*:63*//*76:*/
+#line 1199 "ctangle.w"
+
+void
+scan_repl(t)
+eight_bits t;
+{
+sixteen_bits a;
+if(t==section_name){/*77:*/
+#line 1225 "ctangle.w"
+
+store_two_bytes(0150000);
+if(changing)id_first= change_file_name;
+else id_first= cur_file_name;
+id_loc= id_first+strlen(id_first);
+if(changing)store_two_bytes((sixteen_bits)change_line);
+else store_two_bytes((sixteen_bits)cur_line);
+{int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200);
+app_repl(a%0400);}
+
+/*:77*/
+#line 1205 "ctangle.w"
+;}
+while(1)switch(a= get_next()){
+/*78:*/
+#line 1235 "ctangle.w"
+
+case identifier:a= id_lookup(id_first,id_loc,0)-name_dir;
+app_repl((a/0400)+0200);
+app_repl(a%0400);break;
+case section_name:if(t!=section_name)goto done;
+else{
+/*79:*/
+#line 1268 "ctangle.w"
+{
+char*try_loc= loc;
+while(*try_loc==' '&&try_loc<limit)try_loc++;
+if(*try_loc=='+'&&try_loc<limit)try_loc++;
+while(*try_loc==' '&&try_loc<limit)try_loc++;
+if(*try_loc=='=')err_print("! Missing `@ ' before a named section");
+
+
+
+}
+
+/*:79*/
+#line 1241 "ctangle.w"
+;
+a= cur_section_name-name_dir;
+app_repl((a/0400)+0250);
+app_repl(a%0400);
+/*77:*/
+#line 1225 "ctangle.w"
+
+store_two_bytes(0150000);
+if(changing)id_first= change_file_name;
+else id_first= cur_file_name;
+id_loc= id_first+strlen(id_first);
+if(changing)store_two_bytes((sixteen_bits)change_line);
+else store_two_bytes((sixteen_bits)cur_line);
+{int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200);
+app_repl(a%0400);}
+
+/*:77*/
+#line 1245 "ctangle.w"
+;break;
+}
+case output_defs_code:if(t!=section_name)err_print("! Misplaced @h");
+
+else{
+output_defs_seen= 1;
+a= output_defs_flag;
+app_repl((a/0400)+0200);
+app_repl(a%0400);
+/*77:*/
+#line 1225 "ctangle.w"
+
+store_two_bytes(0150000);
+if(changing)id_first= change_file_name;
+else id_first= cur_file_name;
+id_loc= id_first+strlen(id_first);
+if(changing)store_two_bytes((sixteen_bits)change_line);
+else store_two_bytes((sixteen_bits)cur_line);
+{int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200);
+app_repl(a%0400);}
+
+/*:77*/
+#line 1254 "ctangle.w"
+;
+}
+break;
+case constant:case string:
+/*80:*/
+#line 1279 "ctangle.w"
+
+app_repl(a);
+while(id_first<id_loc){
+if(*id_first=='@'){
+if(*(id_first+1)=='@')id_first++;
+else err_print("! Double @ should be used in string");
+
+}
+app_repl(*id_first++);
+}
+app_repl(a);break;
+
+/*:80*/
+#line 1258 "ctangle.w"
+;
+case ord:
+/*81:*/
+#line 1295 "ctangle.w"
+{
+int c= (eight_bits)*id_first;
+if(c=='\\'){
+c= *++id_first;
+if(c>='0'&&c<='7'){
+c-= '0';
+if(*(id_first+1)>='0'&&*(id_first+1)<='7'){
+c= 8*c+*(++id_first)-'0';
+if(*(id_first+1)>='0'&&*(id_first+1)<='7'&&c<32)
+c= 8*c+*(++id_first)-'0';
+}
+}
+else switch(c){
+case't':c= '\t';break;
+case'n':c= '\n';break;
+case'b':c= '\b';break;
+case'f':c= '\f';break;
+case'v':c= '\v';break;
+case'r':c= '\r';break;
+case'a':c= '\7';break;
+case'?':c= '?';break;
+case'x':
+if(xisdigit(*(id_first+1)))c= *(++id_first)-'0';
+else if(xisxdigit(*(id_first+1))){
+++id_first;
+c= toupper(*id_first)-'A'+10;
+}
+if(xisdigit(*(id_first+1)))c= 16*c+*(++id_first)-'0';
+else if(xisxdigit(*(id_first+1))){
+++id_first;
+c= 16*c+toupper(*id_first)-'A'+10;
+}
+break;
+case'\\':c= '\\';break;
+case'\'':c= '\'';break;
+case'\"':c= '\"';break;
+default:err_print("! Unrecognized escape sequence");
+
+}
+}
+
+app_repl(constant);
+if(c>=100)app_repl('0'+c/100);
+if(c>=10)app_repl('0'+(c/10)%10);
+app_repl('0'+c%10);
+app_repl(constant);
+}
+break;
+
+/*:81*/
+#line 1260 "ctangle.w"
+;
+case definition:case format_code:case begin_C:if(t!=section_name)goto done;
+else{
+err_print("! @d, @f and @c are ignored in C text");continue;
+
+}
+case new_section:goto done;
+
+/*:78*/
+#line 1210 "ctangle.w"
+
+case')':app_repl(a);
+if(t==macro)app_repl(' ');
+break;
+default:app_repl(a);
+}
+done:next_control= (eight_bits)a;
+if(text_ptr> text_info_end)overflow("text");
+cur_text= text_ptr;(++text_ptr)->tok_start= tok_ptr;
+}
+
+/*:76*//*83:*/
+#line 1357 "ctangle.w"
+
+void
+scan_section()
+{
+name_pointer p;
+text_pointer q;
+sixteen_bits a;
+section_count++;no_where= 1;
+if(*(loc-1)=='*'&&show_progress){
+printf("*%d",section_count);update_terminal;
+}
+next_control= 0;
+while(1){
+/*84:*/
+#line 1396 "ctangle.w"
+
+while(next_control<definition)
+
+if((next_control= skip_ahead())==section_name){
+loc-= 2;next_control= get_next();
+}
+
+/*:84*/
+#line 1371 "ctangle.w"
+;
+if(next_control==definition){
+/*85:*/
+#line 1403 "ctangle.w"
+{
+while((next_control= get_next())=='\n');
+if(next_control!=identifier){
+err_print("! Definition flushed, must start with identifier");
+
+continue;
+}
+app_repl(((a= id_lookup(id_first,id_loc,0)-name_dir)/0400)+0200);
+
+app_repl(a%0400);
+if(*loc!='('){
+app_repl(string);app_repl(' ');app_repl(string);
+}
+scan_repl(macro);
+cur_text->text_link= 0;
+}
+
+/*:85*/
+#line 1373 "ctangle.w"
+
+continue;
+}
+if(next_control==begin_C){
+p= name_dir;break;
+}
+if(next_control==section_name){
+p= cur_section_name;
+/*86:*/
+#line 1428 "ctangle.w"
+
+while((next_control= get_next())=='+');
+if(next_control!='='&&next_control!=eq_eq)
+continue;
+
+/*:86*/
+#line 1381 "ctangle.w"
+;
+break;
+}
+return;
+}
+no_where= print_where= 0;
+/*87:*/
+#line 1433 "ctangle.w"
+
+/*88:*/
+#line 1438 "ctangle.w"
+
+store_two_bytes((sixteen_bits)(0150000+section_count));
+
+
+/*:88*/
+#line 1434 "ctangle.w"
+;
+scan_repl(section_name);
+/*89:*/
+#line 1442 "ctangle.w"
+
+if(p==name_dir||p==0){
+(last_unnamed)->text_link= cur_text-text_info;last_unnamed= cur_text;
+}
+else if(p->equiv==(char*)text_info)p->equiv= (char*)cur_text;
+
+else{
+q= (text_pointer)p->equiv;
+while(q->text_link<section_flag)
+q= q->text_link+text_info;
+q->text_link= cur_text-text_info;
+}
+cur_text->text_link= section_flag;
+
+
+/*:89*/
+#line 1436 "ctangle.w"
+;
+
+/*:87*/
+#line 1387 "ctangle.w"
+;
+}
+
+/*:83*//*91:*/
+#line 1460 "ctangle.w"
+
+void
+phase_one(){
+phase= 1;
+section_count= 0;
+reset_input();
+skip_limbo();
+while(!input_has_ended)scan_section();
+check_complete();
+phase= 2;
+}
+
+/*:91*//*93:*/
+#line 1478 "ctangle.w"
+
+void
+skip_limbo()
+{
+char c;
+while(1){
+if(loc> limit&&get_line()==0)return;
+*(limit+1)= '@';
+while(*loc!='@')loc++;
+if(loc++<=limit){
+c= *loc++;
+if(ccode[(eight_bits)c]==new_section)break;
+switch(ccode[(eight_bits)c]){
+case translit_code:/*94:*/
+#line 1507 "ctangle.w"
+
+while(xisspace(*loc)&&loc<limit)loc++;
+loc+= 3;
+if(loc> limit||!xisxdigit(*(loc-3))||!xisxdigit(*(loc-2))
+||(*(loc-3)>='0'&&*(loc-3)<='7')||!xisspace(*(loc-1)))
+err_print("! Improper hex number following @l");
+
+else{
+unsigned i;
+char*beg;
+sscanf(loc-3,"%x",&i);
+while(xisspace(*loc)&&loc<limit)loc++;
+beg= loc;
+while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_'))loc++;
+if(loc-beg>=translit_length)
+err_print("! Replacement string in @l too long");
+
+else{
+strncpy(translit[i-0200],beg,loc-beg);
+translit[i-0200][loc-beg]= '\0';
+}
+}
+
+/*:94*/
+#line 1491 "ctangle.w"
+;break;
+case format_code:case'@':break;
+case control_text:if(c=='q'||c=='Q'){
+while((c= skip_ahead())=='@');
+if(*(loc-1)!='>')
+err_print("! Double @ should be used in control text");
+
+break;
+}
+default:err_print("! Double @ should be used in limbo");
+
+}
+}
+}
+}
+
+/*:93*//*95:*/
+#line 1533 "ctangle.w"
+
+void
+print_stats(){
+printf("\nMemory usage statistics:\n");
+printf("%ld names (out of %ld)\n",
+(long)(name_ptr-name_dir),(long)max_names);
+printf("%ld replacement texts (out of %ld)\n",
+(long)(text_ptr-text_info),(long)max_texts);
+printf("%ld bytes (out of %ld)\n",
+(long)(byte_ptr-byte_mem),(long)max_bytes);
+printf("%ld tokens (out of %ld)\n",
+(long)(tok_ptr-tok_mem),(long)max_toks);
+}
+
+/*:95*/
diff --git a/Build/source/texk/web2c/cwebdir/ctangle.rc b/Build/source/texk/web2c/cwebdir/ctangle.rc
new file mode 100644
index 00000000000..c2b73323b15
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctangle.rc
@@ -0,0 +1,34 @@
+/* ctangle.rc: ctangle resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " ctangle 3.63"
+
+#define VER_INTERNALNAME_STR "ctangle"
+#define VER_ORIGINALFILENAME_STR "ctangle.exe"
+
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth"
+
+#define VER_FILEDESCRIPTION_STR "CTangle"
+
+#include <texlive.version>
+
+/* afm2tfm.rc ends here */
diff --git a/Build/source/texk/web2c/cwebdir/ctangle.w b/Build/source/texk/web2c/cwebdir/ctangle.w
new file mode 100644
index 00000000000..6cdcfd5db06
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/ctangle.w
@@ -0,0 +1,1554 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.64 --- February 2002
+% (same as Version 3.5 except for minor corrections)
+% (also quotes backslashes in file names of #line directives)
+
+% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+% Here is TeX material that gets inserted after \input cwebmac
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\char'174} % vertical (|) in typewriter font
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+
+\def\title{CTANGLE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CTANGLE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+@s not_eq normal @q unreserve a C++ keyword @>
+
+@** Introduction.
+This is the \.{CTANGLE} program by Silvio Levy and Donald E. Knuth,
+based on \.{TANGLE} by Knuth.
+We are thankful to
+Nelson Beebe, Hans-Hermann Bode (to whom the \CPLUSPLUS/ adaptation is due),
+Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
+Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.
+
+The ``banner line'' defined here should be changed whenever \.{CTANGLE}
+is modified.
+
+@d banner "This is CTANGLE (Version 3.64)\n"
+
+@c
+@<Include files@>@/
+@h
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/
+@<Typedef declarations@>@/
+@<Global variables@>@/
+@<Predeclaration of procedures@>@/
+
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+
+@ \.{CTANGLE} has a fairly straightforward outline. It operates in
+two phases: First it reads the source file, saving the \CEE/ code in
+compressed form; then it shuffles and outputs the code.
+
+Please read the documentation for \.{common}, the set of routines common
+to \.{CTANGLE} and \.{CWEAVE}, before proceeding further.
+
+@c
+int main (ac, av)
+int ac;
+char **av;
+{
+ argc=ac; argv=av;
+ program=ctangle;
+ @<Set initial values@>;
+ common_init();
+ if (show_banner) printf(banner); /* print a ``banner line'' */
+ phase_one(); /* read all the user's text and compress it into |tok_mem| */
+ phase_two(); /* output the contents of the compressed tables */
+ return wrap_up(); /* and exit gracefully */
+}
+
+@ The following parameters were sufficient in the original \.{TANGLE} to
+handle \TEX/,
+so they should be sufficient for most applications of \.{CTANGLE}.
+If you change |max_bytes|, |max_names|, or |hash_size| you should also
+change them in the file |"common.w"|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names; used in |"common.w"| */
+@d max_toks 270000 /* number of bytes in compressed \CEE/ code */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_texts 2500 /* number of replacement texts, must be less than 10240 */
+@d hash_size 353 /* should be prime; used in |"common.w"| */
+@d longest_name 10000 /* section names shouldn't be longer than this */
+@d stack_size 50 /* number of simultaneous levels of macro expansion */
+@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */
+
+@ The next few sections contain stuff from the file |"common.w"| that must
+be included in both |"ctangle.w"| and |"cweave.w"|. It appears in
+file |"common.h"|, which needs to be updated when |"common.w"| changes.
+
+@i common.h
+
+@* Data structures exclusive to {\tt CTANGLE}.
+We've already seen that the |byte_mem| array holds the names of identifiers,
+strings, and sections;
+the |tok_mem| array holds the replacement texts
+for sections. Allocation is sequential, since things are deleted only
+during Phase II, and only in a last-in-first-out manner.
+
+A \&{text} variable is a structure containing a pointer into
+|tok_mem|, which tells where the corresponding text starts, and an
+integer |text_link|, which, as we shall see later, is used to connect
+pieces of text that have the same name. All the \&{text}s are stored in
+the array |text_info|, and we use a |text_pointer| variable to refer
+to them.
+
+The first position of |tok_mem| that is unoccupied by
+replacement text is called |tok_ptr|, and the first unused location of
+|text_info| is called |text_ptr|. Thus we usually have the identity
+|text_ptr->tok_start==tok_ptr|.
+
+If your machine does not support |unsigned char| you should change
+the definition of \&{eight\_bits} to |unsigned short|.
+@^system dependencies@>
+
+@<Typed...@>=
+typedef struct {
+ eight_bits *tok_start; /* pointer into |tok_mem| */
+ sixteen_bits text_link; /* relates replacement texts */
+} text;
+typedef text *text_pointer;
+
+@ @<Glob...@>=
+text text_info[max_texts];
+text_pointer text_info_end=text_info+max_texts-1;
+text_pointer text_ptr; /* first unused position in |text_info| */
+eight_bits tok_mem[max_toks];
+eight_bits *tok_mem_end=tok_mem+max_toks-1;
+eight_bits *tok_ptr; /* first unused position in |tok_mem| */
+
+@ @<Set init...@>=
+text_info->tok_start=tok_ptr=tok_mem;
+text_ptr=text_info+1; text_ptr->tok_start=tok_mem;
+ /* this makes replacement text 0 of length zero */
+
+@ If |p| is a pointer to a section name, |p->equiv| is a pointer to its
+replacement text, an element of the array |text_info|.
+
+@d equiv equiv_or_xref /* info corresponding to names */
+
+@ @<Set init...@>=
+name_dir->equiv=(char *)text_info; /* the undefined section has no replacement text */
+
+@ Here's the procedure that decides whether a name of length |l|
+starting at position |first| equals the identifier pointed to by |p|:
+
+@c
+int names_match(p,first,l)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+int l; /* length of identifier */
+{
+ if (length(p)!=l) return 0;
+ return !strncmp(first,p->byte_start,l);
+}
+
+@ The common lookup routine refers to separate routines |init_node| and
+|init_p| when the data structure grows. Actually |init_p| is called only by
+\.{CWEAVE}, but we need to declare a dummy version so that
+the loader won't complain of its absence.
+
+@c
+void
+init_node(node)
+name_pointer node;
+{
+ node->equiv=(char *)text_info;
+}
+void
+init_p() {}
+
+@* Tokens.
+Replacement texts, which represent \CEE/ code in a compressed format,
+appear in |tok_mem| as mentioned above. The codes in
+these texts are called `tokens'; some tokens occupy two consecutive
+eight-bit byte positions, and the others take just one byte.
+
+If $p$ points to a replacement text, |p->tok_start| is the |tok_mem| position
+of the first eight-bit code of that text. If |p->text_link==0|,
+this is the replacement text for a macro, otherwise it is the replacement
+text for a section. In the latter case |p->text_link| is either equal to
+|section_flag|, which means that there is no further text for this section, or
+|p->text_link| points to a continuation of this replacement text; such
+links are created when several sections have \CEE/ texts with the same
+name, and they also tie together all the \CEE/ texts of unnamed sections.
+The replacement text pointer for the first unnamed section appears in
+|text_info->text_link|, and the most recent such pointer is |last_unnamed|.
+
+@d section_flag max_texts /* final |text_link| in section replacement texts */
+
+@<Glob...@>=
+text_pointer last_unnamed; /* most recent replacement text of unnamed section */
+
+@ @<Set init...@>= last_unnamed=text_info; text_info->text_link=0;
+
+@ If the first byte of a token is less than |0200|, the token occupies a
+single byte. Otherwise we make a sixteen-bit token by combining two consecutive
+bytes |a| and |b|. If |0200<=a<0250|, then |(a-0200)@t${}\times2^8$@>+b|
+points to an identifier; if |0250<=a<0320|, then
+|(a-0250)@t${}\times2^8$@>+b| points to a section name
+(or, if it has the special value |output_defs_flag|,
+to the area where the preprocessor definitions are stored); and if
+|0320<=a<0400|, then |(a-0320)@t${}\times2^8$@>+b| is the number of the section
+in which the current replacement text appears.
+
+Codes less than |0200| are 7-bit |char| codes that represent themselves.
+Some of the 7-bit codes will not be present, however, so we can
+use them for special purposes. The following symbolic names are used:
+
+\yskip \hang |join| denotes the concatenation of adjacent items with no
+space or line breaks allowed between them (the \.{@@\&} operation of \.{CWEB}).
+
+\hang |string| denotes the beginning or end of a string, verbatim
+construction or numerical constant.
+@^ASCII code dependencies@>
+
+@d string 02 /* takes the place of extended ASCII \.{\char2} */
+@d join 0177 /* takes the place of ASCII delete */
+@d output_defs_flag (2*024000-1)
+
+@ The following procedure is used to enter a two-byte value into
+|tok_mem| when a replacement text is being generated.
+
+@c
+void
+store_two_bytes(x)
+sixteen_bits x;
+{
+ if (tok_ptr+2>tok_mem_end) overflow("token");
+ *tok_ptr++=x>>8; /* store high byte */
+ *tok_ptr++=x&0377; /* store low byte */
+}
+
+@** Stacks for output. The output process uses a stack to keep track
+of what is going on at different ``levels'' as the sections are being
+written out. Entries on this stack have five parts:
+
+\yskip\hang |end_field| is the |tok_mem| location where the replacement
+text of a particular level will end;
+
+\hang |byte_field| is the |tok_mem| location from which the next token
+on a particular level will be read;
+
+\hang |name_field| points to the name corresponding to a particular level;
+
+\hang |repl_field| points to the replacement text currently being read
+at a particular level;
+
+\hang |section_field| is the section number, or zero if this is a macro.
+
+\yskip\noindent The current values of these five quantities are referred to
+quite frequently, so they are stored in a separate place instead of in
+the |stack| array. We call the current values |cur_end|, |cur_byte|,
+|cur_name|, |cur_repl|, and |cur_section|.
+
+The global variable |stack_ptr| tells how many levels of output are
+currently in progress. The end of all output occurs when the stack is
+empty, i.e., when |stack_ptr==stack|.
+
+@<Typed...@>=
+typedef struct {
+ eight_bits *end_field; /* ending location of replacement text */
+ eight_bits *byte_field; /* present location within replacement text */
+ name_pointer name_field; /* |byte_start| index for text being output */
+ text_pointer repl_field; /* |tok_start| index for text being output */
+ sixteen_bits section_field; /* section number or zero if not a section */
+} output_state;
+typedef output_state *stack_pointer;
+
+@ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */
+@d cur_byte cur_state.byte_field /* location of next output byte in |tok_mem|*/
+@d cur_name cur_state.name_field /* pointer to current name being expanded */
+@d cur_repl cur_state.repl_field /* pointer to current replacement text */
+@d cur_section cur_state.section_field /* current section number being expanded */
+
+@<Global...@>=
+output_state cur_state; /* |cur_end|, |cur_byte|, |cur_name|, |cur_repl|,
+ and |cur_section| */
+output_state stack[stack_size+1]; /* info for non-current levels */
+stack_pointer stack_ptr; /* first unused location in the output state stack */
+stack_pointer stack_end=stack+stack_size; /* end of |stack| */
+
+@ To get the output process started, we will perform the following
+initialization steps. We may assume that |text_info->text_link| is nonzero,
+since it points to the \CEE/ text in the first unnamed section that generates
+code; if there are no such sections, there is nothing to output, and an
+error message will have been generated before we do any of the initialization.
+
+@<Initialize the output stacks@>=
+stack_ptr=stack+1; cur_name=name_dir; cur_repl=text_info->text_link+text_info;
+cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start; cur_section=0;
+
+@ When the replacement text for name |p| is to be inserted into the output,
+the following subroutine is called to save the old level of output and get
+the new one going.
+
+We assume that the \CEE/ compiler can copy structures.
+@^system dependencies@>
+
+@c
+void
+push_level(p) /* suspends the current level */
+name_pointer p;
+{
+ if (stack_ptr==stack_end) overflow("stack");
+ *stack_ptr=cur_state;
+ stack_ptr++;
+ if (p!=NULL) { /* |p==NULL| means we are in |output_defs| */
+ cur_name=p; cur_repl=(text_pointer)p->equiv;
+ cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;
+ cur_section=0;
+ }
+}
+
+@ When we come to the end of a replacement text, the |pop_level| subroutine
+does the right thing: It either moves to the continuation of this replacement
+text or returns the state to the most recently stacked level.
+
+@c
+void
+pop_level(flag) /* do this when |cur_byte| reaches |cur_end| */
+int flag; /* |flag==0| means we are in |output_defs| */
+{
+ if (flag && cur_repl->text_link<section_flag) { /* link to a continuation */
+ cur_repl=cur_repl->text_link+text_info; /* stay on the same level */
+ cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;
+ return;
+ }
+ stack_ptr--; /* go down to the previous level */
+ if (stack_ptr>stack) cur_state=*stack_ptr;
+}
+
+@ The heart of the output procedure is the function |get_output|,
+which produces the next token of output and sends it on to the lower-level
+function |out_char|. The main purpose of |get_output| is to handle the
+necessary stacking and unstacking. It sends the value |section_number|
+if the next output begins or ends the replacement text of some section,
+in which case |cur_val| is that section's number (if beginning) or the
+negative of that value (if ending). (A section number of 0 indicates
+not the beginning or ending of a section, but a \&{\#line} command.)
+And it sends the value |identifier|
+if the next output is an identifier, in which case
+|cur_val| points to that identifier name.
+
+@d section_number 0201 /* code returned by |get_output| for section numbers */
+@d identifier 0202 /* code returned by |get_output| for identifiers */
+
+@<Global...@>=
+int cur_val; /* additional information corresponding to output token */
+
+@ If |get_output| finds that no more output remains, it returns with
+|stack_ptr==stack|.
+@^high-bit character handling@>
+
+@c
+void
+get_output() /* sends next token to |out_char| */
+{
+ sixteen_bits a; /* value of current byte */
+ restart: if (stack_ptr==stack) return;
+ if (cur_byte==cur_end) {
+ cur_val=-((int)cur_section); /* cast needed because of sign extension */
+ pop_level(1);
+ if (cur_val==0) goto restart;
+ out_char(section_number); return;
+ }
+ a=*cur_byte++;
+ if (out_state==verbatim && a!=string && a!=constant && a!='\n')
+ C_putc(a); /* a high-bit character can occur in a string */
+ else if (a<0200) out_char(a); /* one-byte token */
+ else {
+ a=(a-0200)*0400+*cur_byte++;
+ switch (a/024000) { /* |024000==(0250-0200)*0400| */
+ case 0: cur_val=a; out_char(identifier); break;
+ case 1: if (a==output_defs_flag) output_defs();
+ else @<Expand section |a-024000|, |goto restart|@>;
+ break;
+ default: cur_val=a-050000; if (cur_val>0) cur_section=cur_val;
+ out_char(section_number);
+ }
+ }
+}
+
+@ The user may have forgotten to give any \CEE/ text for a section name,
+or the \CEE/ text may have been associated with a different name by mistake.
+
+@<Expand section |a-...@>=
+{
+ a-=024000;
+ if ((a+name_dir)->equiv!=(char *)text_info) push_level(a+name_dir);
+ else if (a!=0) {
+ printf("\n! Not present: <");
+ print_section_name(a+name_dir); err_print(">");
+@.Not present: <section name>@>
+ }
+ goto restart;
+}
+
+@* Producing the output.
+The |get_output| routine above handles most of the complexity of output
+generation, but there are two further considerations that have a nontrivial
+effect on \.{CTANGLE}'s algorithms.
+
+@ First,
+we want to make sure that the output has spaces and line breaks in
+the right places (e.g., not in the middle of a string or a constant or an
+identifier, not at a `\.{@@\&}' position
+where quantities are being joined together, and certainly after an \.=
+because the \CEE/ compiler thinks \.{=-} is ambiguous).
+
+The output process can be in one of following states:
+
+\yskip\hang |num_or_id| means that the last item in the buffer is a number or
+identifier, hence a blank space or line break must be inserted if the next
+item is also a number or identifier.
+
+\yskip\hang |unbreakable| means that the last item in the buffer was followed
+by the \.{@@\&} operation that inhibits spaces between it and the next item.
+
+\yskip\hang |verbatim| means we're copying only character tokens, and
+that they are to be output exactly as stored. This is the case during
+strings, verbatim constructions and numerical constants.
+
+\yskip\hang |post_slash| means we've just output a slash.
+
+\yskip\hang |normal| means none of the above.
+
+\yskip\noindent Furthermore, if the variable |protect| is positive, newlines
+are preceded by a `\.\\'.
+
+@d normal 0 /* non-unusual state */
+@d num_or_id 1 /* state associated with numbers and identifiers */
+@d post_slash 2 /* state following a \./ */
+@d unbreakable 3 /* state associated with \.{@@\&} */
+@d verbatim 4 /* state in the middle of a string */
+
+@<Global...@>=
+eight_bits out_state; /* current status of partial output */
+boolean protect; /* should newline characters be quoted? */
+
+@ Here is a routine that is invoked when we want to output the current line.
+During the output process, |cur_line| equals the number of the next line
+to be output.
+
+@c
+void
+flush_buffer() /* writes one line to output file */
+{
+ C_putc('\n');
+ if (cur_line % 100 == 0 && show_progress) {
+ printf(".");
+ if (cur_line % 500 == 0) printf("%d",cur_line);
+ update_terminal; /* progress report */
+ }
+ cur_line++;
+}
+
+@ Second, we have modified the original \.{TANGLE} so that it will write output
+on multiple files.
+If a section name is introduced in at least one place by \.{@@(}
+instead of \.{@@<}, we treat it as the name of a file.
+All these special sections are saved on a stack, |output_files|.
+We write them out after we've done the unnamed section.
+
+@d max_files 256
+@<Glob...@>=
+name_pointer output_files[max_files];
+name_pointer *cur_out_file, *end_output_files, *an_output_file;
+char cur_section_name_char; /* is it |'<'| or |'('| */
+char output_file_name[longest_name]; /* name of the file */
+
+@ We make |end_output_files| point just beyond the end of
+|output_files|. The stack pointer
+|cur_out_file| starts out there. Every time we see a new file, we
+decrement |cur_out_file| and then write it in.
+@<Set initial...@>=
+cur_out_file=end_output_files=output_files+max_files;
+
+@ @<If it's not there, add |cur_section_name| to the output file stack, or
+complain we're out of room@>=
+{
+ for (an_output_file=cur_out_file;
+ an_output_file<end_output_files; an_output_file++)
+ if (*an_output_file==cur_section_name) break;
+ if (an_output_file==end_output_files) {
+ if (cur_out_file>output_files)
+ *--cur_out_file=cur_section_name;
+ else {
+ overflow("output files");
+ }
+ }
+}
+
+@* The big output switch. Here then is the routine that does the
+output.
+
+@<Predecl...@>=
+void phase_two();
+
+@ @c
+void
+phase_two () {
+ web_file_open=0;
+ cur_line=1;
+ @<Initialize the output stacks@>;
+ @<Output macro definitions if appropriate@>;
+ if (text_info->text_link==0 && cur_out_file==end_output_files) {
+ printf("\n! No program text was specified."); mark_harmless;
+@.No program text...@>
+ }
+ else {
+ if(cur_out_file==end_output_files) {
+ if(show_progress)
+ printf("\nWriting the output file (%s):",C_file_name);
+ }
+ else {
+ if (show_progress) {
+ printf("\nWriting the output files:");
+@.Writing the output...@>
+ printf(" (%s)",C_file_name);
+ update_terminal;
+ }
+ if (text_info->text_link==0) goto writeloop;
+ }
+ while (stack_ptr>stack) get_output();
+ flush_buffer();
+writeloop: @<Write all the named output files@>;
+ if(show_happiness) printf("\nDone.");
+ }
+}
+
+@ To write the named output files, we proceed as for the unnamed
+section.
+The only subtlety is that we have to open each one.
+
+@<Write all the named output files@>=
+for (an_output_file=end_output_files; an_output_file>cur_out_file;) {
+ an_output_file--;
+ sprint_section_name(output_file_name,*an_output_file);
+ fclose(C_file);
+ C_file=fopen(output_file_name,"w");
+ if (C_file ==0) fatal("! Cannot open output file:",output_file_name);
+@.Cannot open output file@>
+ printf("\n(%s)",output_file_name); update_terminal;
+ cur_line=1;
+ stack_ptr=stack+1;
+ cur_name= (*an_output_file);
+ cur_repl= (text_pointer)cur_name->equiv;
+ cur_byte=cur_repl->tok_start;
+ cur_end=(cur_repl+1)->tok_start;
+ while (stack_ptr > stack) get_output();
+ flush_buffer();
+}
+
+@ If a \.{@@h} was not encountered in the input,
+we go through the list of replacement texts and copy the ones
+that refer to macros, preceded by the \.{\#define} preprocessor command.
+
+@<Output macro definitions if appropriate@>=
+ if (!output_defs_seen)
+ output_defs();
+
+@ @<Glob...@>=
+boolean output_defs_seen=0;
+
+@ @<Predecl...@>=
+void output_defs();
+
+@ @c
+void
+output_defs()
+{
+ sixteen_bits a;
+ push_level(NULL);
+ for (cur_text=text_info+1; cur_text<text_ptr; cur_text++)
+ if (cur_text->text_link==0) { /* |cur_text| is the text for a macro */
+ cur_byte=cur_text->tok_start;
+ cur_end=(cur_text+1)->tok_start;
+ C_printf("%s","#define ");
+ out_state=normal;
+ protect=1; /* newlines should be preceded by |'\\'| */
+ while (cur_byte<cur_end) {
+ a=*cur_byte++;
+ if (cur_byte==cur_end && a=='\n') break; /* disregard a final newline */
+ if (out_state==verbatim && a!=string && a!=constant && a!='\n')
+ C_putc(a); /* a high-bit character can occur in a string */
+@^high-bit character handling@>
+ else if (a<0200) out_char(a); /* one-byte token */
+ else {
+ a=(a-0200)*0400+*cur_byte++;
+ if (a<024000) { /* |024000==(0250-0200)*0400| */
+ cur_val=a; out_char(identifier);
+ }
+ else if (a<050000) { confusion("macro defs have strange char");}
+ else {
+ cur_val=a-050000; cur_section=cur_val; out_char(section_number);
+ }
+ /* no other cases */
+ }
+ }
+ protect=0;
+ flush_buffer();
+ }
+ pop_level(0);
+}
+
+@ A many-way switch is used to send the output. Note that this function
+is not called if |out_state==verbatim|, except perhaps with arguments
+|'\n'| (protect the newline), |string| (end the string), or |constant|
+(end the constant).
+
+@<Predecl...@>=
+static void out_char();
+
+@ @c
+static void
+out_char(cur_char)
+eight_bits cur_char;
+{
+ char *j, *k; /* pointer into |byte_mem| */
+restart:
+ switch (cur_char) {
+ case '\n': if (protect && out_state!=verbatim) C_putc(' ');
+ if (protect || out_state==verbatim) C_putc('\\');
+ flush_buffer(); if (out_state!=verbatim) out_state=normal; break;
+ @/@t\4@>@<Case of an identifier@>;
+ @/@t\4@>@<Case of a section number@>;
+ @/@t\4@>@<Cases like \.{!=}@>;
+ case '=': case '>': C_putc(cur_char); C_putc(' ');
+ out_state=normal; break;
+ case join: out_state=unbreakable; break;
+ case constant: if (out_state==verbatim) {
+ out_state=num_or_id; break;
+ }
+ if(out_state==num_or_id) C_putc(' '); out_state=verbatim; break;
+ case string: if (out_state==verbatim) out_state=normal;
+ else out_state=verbatim; break;
+ case '/': C_putc('/'); out_state=post_slash; break;
+ case '*': if (out_state==post_slash) C_putc(' ');
+ /* fall through */
+ default: C_putc(cur_char); out_state=normal; break;
+ }
+}
+
+@ @<Cases like \.{!=}@>=
+case plus_plus: C_putc('+'); C_putc('+'); out_state=normal; break;
+case minus_minus: C_putc('-'); C_putc('-'); out_state=normal; break;
+case minus_gt: C_putc('-'); C_putc('>'); out_state=normal; break;
+case gt_gt: C_putc('>'); C_putc('>'); out_state=normal; break;
+case eq_eq: C_putc('='); C_putc('='); out_state=normal; break;
+case lt_lt: C_putc('<'); C_putc('<'); out_state=normal; break;
+case gt_eq: C_putc('>'); C_putc('='); out_state=normal; break;
+case lt_eq: C_putc('<'); C_putc('='); out_state=normal; break;
+case not_eq: C_putc('!'); C_putc('='); out_state=normal; break;
+case and_and: C_putc('&'); C_putc('&'); out_state=normal; break;
+case or_or: C_putc('|'); C_putc('|'); out_state=normal; break;
+case dot_dot_dot: C_putc('.'); C_putc('.'); C_putc('.'); out_state=normal;
+ break;
+case colon_colon: C_putc(':'); C_putc(':'); out_state=normal; break;
+case period_ast: C_putc('.'); C_putc('*'); out_state=normal; break;
+case minus_gt_ast: C_putc('-'); C_putc('>'); C_putc('*'); out_state=normal;
+ break;
+
+@ When an identifier is output to the \CEE/ file, characters in the
+range 128--255 must be changed into something else, so the \CEE/
+compiler won't complain. By default, \.{CTANGLE} converts the
+character with code $16 x+y$ to the three characters `\.X$xy$', but
+a different transliteration table can be specified. Thus a German
+might want {\it gr\"un\/} to appear as a still readable \.{gruen}.
+This makes debugging a lot less confusing.
+
+@d translit_length 10
+
+@<Glo...@>=
+char translit[128][translit_length];
+
+@ @<Set init...@>=
+{
+ int i;
+ for (i=0;i<128;i++) sprintf(translit[i],"X%02X",(unsigned)(128+i));
+}
+
+@ @<Case of an identifier@>=
+case identifier:
+ if (out_state==num_or_id) C_putc(' ');
+ j=(cur_val+name_dir)->byte_start;
+ k=(cur_val+name_dir+1)->byte_start;
+ while (j<k) {
+ if ((unsigned char)(*j)<0200) C_putc(*j);
+@^high-bit character handling@>
+ else C_printf("%s",translit[(unsigned char)(*j)-0200]);
+ j++;
+ }
+ out_state=num_or_id; break;
+
+@ @<Case of a sec...@>=
+case section_number:
+ if (cur_val>0) C_printf("/*%d:*/",cur_val);
+ else if(cur_val<0) C_printf("/*:%d*/",-cur_val);
+ else if (protect) {
+ cur_byte +=4; /* skip line number and file name */
+ cur_char = '\n';
+ goto restart;
+ } else {
+ sixteen_bits a;
+ a=0400* *cur_byte++;
+ a+=*cur_byte++; /* gets the line number */
+ C_printf("\n#line %d \"",a);
+@:line}{\.{\#line}@>
+ cur_val=*cur_byte++;
+ cur_val=0400*(cur_val-0200)+ *cur_byte++; /* points to the file name */
+ for (j=(cur_val+name_dir)->byte_start, k=(cur_val+name_dir+1)->byte_start;
+ j<k; j++) {
+ if (*j=='\\' || *j=='"') C_putc('\\');
+ C_putc(*j);
+ }
+ C_printf("%s","\"\n");
+ }
+ break;
+
+@** Introduction to the input phase.
+We have now seen that \.{CTANGLE} will be able to output the full
+\CEE/ program, if we can only get that program into the byte memory in
+the proper format. The input process is something like the output process
+in reverse, since we compress the text as we read it in and we expand it
+as we write it out.
+
+There are three main input routines. The most interesting is the one that gets
+the next token of a \CEE/ text; the other two are used to scan rapidly past
+\TEX/ text in the \.{CWEB} source code. One of the latter routines will jump to
+the next token that starts with `\.{@@}', and the other skips to the end
+of a \CEE/ comment.
+
+@ Control codes in \.{CWEB} begin with `\.{@@}', and the next character
+identifies the code. Some of these are of interest only to \.{CWEAVE},
+so \.{CTANGLE} ignores them; the others are converted by \.{CTANGLE} into
+internal code numbers by the |ccode| table below. The ordering
+of these internal code numbers has been chosen to simplify the program logic;
+larger numbers are given to the control codes that denote more significant
+milestones.
+
+@d ignore 0 /* control code of no interest to \.{CTANGLE} */
+@d ord 0302 /* control code for `\.{@@'}' */
+@d control_text 0303 /* control code for `\.{@@t}', `\.{@@\^}', etc. */
+@d translit_code 0304 /* control code for `\.{@@l}' */
+@d output_defs_code 0305 /* control code for `\.{@@h}' */
+@d format_code 0306 /* control code for `\.{@@f}' */
+@d definition 0307 /* control code for `\.{@@d}' */
+@d begin_C 0310 /* control code for `\.{@@c}' */
+@d section_name 0311 /* control code for `\.{@@<}' */
+@d new_section 0312 /* control code for `\.{@@\ }' and `\.{@@*}' */
+
+@<Global...@>=
+eight_bits ccode[256]; /* meaning of a char following \.{@@} */
+
+@ @<Set ini...@>= {
+ int c; /* must be |int| so the |for| loop will end */
+ for (c=0; c<256; c++) ccode[c]=ignore;
+ ccode[' ']=ccode['\t']=ccode['\n']=ccode['\v']=ccode['\r']=ccode['\f']
+ =ccode['*']=new_section;
+ ccode['@@']='@@'; ccode['=']=string;
+ ccode['d']=ccode['D']=definition;
+ ccode['f']=ccode['F']=ccode['s']=ccode['S']=format_code;
+ ccode['c']=ccode['C']=ccode['p']=ccode['P']=begin_C;
+ ccode['^']=ccode[':']=ccode['.']=ccode['t']=ccode['T']=
+ ccode['q']=ccode['Q']=control_text;
+ ccode['h']=ccode['H']=output_defs_code;
+ ccode['l']=ccode['L']=translit_code;
+ ccode['&']=join;
+ ccode['<']=ccode['(']=section_name;
+ ccode['\'']=ord;
+}
+
+@ The |skip_ahead| procedure reads through the input at fairly high speed
+until finding the next non-ignorable control code, which it returns.
+
+@c
+eight_bits
+skip_ahead() /* skip to next control code */
+{
+ eight_bits c; /* control code found */
+ while (1) {
+ if (loc>limit && (get_line()==0)) return(new_section);
+ *(limit+1)='@@';
+ while (*loc!='@@') loc++;
+ if (loc<=limit) {
+ loc++; c=ccode[(eight_bits)*loc]; loc++;
+ if (c!=ignore || *(loc-1)=='>') return(c);
+ }
+ }
+}
+
+@ The |skip_comment| procedure reads through the input at somewhat high
+speed in order to pass over comments, which \.{CTANGLE} does not transmit
+to the output. If the comment is introduced by \.{/*}, |skip_comment|
+proceeds until finding the end-comment token \.{*/} or a newline; in the
+latter case |skip_comment| will be called again by |get_next|, since the
+comment is not finished. This is done so that the each newline in the
+\CEE/ part of a section is copied to the output; otherwise the \&{\#line}
+commands inserted into the \CEE/ file by the output routines become useless.
+On the other hand, if the comment is introduced by \.{//} (i.e., if it
+is a \CPLUSPLUS/ ``short comment''), it always is simply delimited by the next
+newline. The boolean argument |is_long_comment| distinguishes between
+the two types of comments.
+
+If |skip_comment| comes to the end of the section, it prints an error message.
+No comment, long or short, is allowed to contain `\.{@@\ }' or `\.{@@*}'.
+
+@<Global...@>=
+boolean comment_continues=0; /* are we scanning a comment? */
+
+@ @c
+int skip_comment(is_long_comment) /* skips over comments */
+boolean is_long_comment;
+{
+ char c; /* current character */
+ while (1) {
+ if (loc>limit) {
+ if (is_long_comment) {
+ if(get_line()) return(comment_continues=1);
+ else{
+ err_print("! Input ended in mid-comment");
+@.Input ended in mid-comment@>
+ return(comment_continues=0);
+ }
+ }
+ else return(comment_continues=0);
+ }
+ c=*(loc++);
+ if (is_long_comment && c=='*' && *loc=='/') {
+ loc++; return(comment_continues=0);
+ }
+ if (c=='@@') {
+ if (ccode[(eight_bits)*loc]==new_section) {
+ err_print("! Section name ended in mid-comment"); loc--;
+@.Section name ended in mid-comment@>
+ return(comment_continues=0);
+ }
+ else loc++;
+ }
+ }
+}
+
+@* Inputting the next token.
+
+@d constant 03
+
+@<Global...@>=
+name_pointer cur_section_name; /* name of section just scanned */
+int no_where; /* suppress |print_where|? */
+
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+
+@ As one might expect, |get_next| consists mostly of a big switch
+that branches to the various special cases that can arise.
+
+@d isxalpha(c) ((c)=='_' || (c)=='$')
+ /* non-alpha characters allowed in identifier */
+@d ishigh(c) ((unsigned char)(c)>0177)
+@^high-bit character handling@>
+
+@c
+eight_bits
+get_next() /* produces the next input token */
+{
+ static int preprocessing=0;
+ eight_bits c; /* the current character */
+ while (1) {
+ if (loc>limit) {
+ if (preprocessing && *(limit-1)!='\\') preprocessing=0;
+ if (get_line()==0) return(new_section);
+ else if (print_where && !no_where) {
+ print_where=0;
+ @<Insert the line number into |tok_mem|@>;
+ }
+ else return ('\n');
+ }
+ c=*loc;
+ if (comment_continues || (c=='/' && (*(loc+1)=='*' || *(loc+1)=='/'))) {
+ skip_comment(comment_continues||*(loc+1)=='*');
+ /* scan to end of comment or newline */
+ if (comment_continues) return('\n');
+ else continue;
+ }
+ loc++;
+ if (xisdigit(c) || c=='.') @<Get a constant@>@;
+ else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"')))
+ @<Get a string@>@;
+ else if (isalpha(c) || isxalpha(c) || ishigh(c))
+ @<Get an identifier@>@;
+ else if (c=='@@') @<Get control code and possible section name@>@;
+ else if (xisspace(c)) {
+ if (!preprocessing || loc>limit) continue;
+ /* we don't want a blank after a final backslash */
+ else return(' '); /* ignore spaces and tabs, unless preprocessing */
+ }
+ else if (c=='#' && loc==buffer+1) preprocessing=1;
+ mistake: @<Compress two-symbol operator@>@;
+ return(c);
+ }
+}
+
+@ The following code assigns values to the combinations \.{++},
+\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{||} and
+\.{\&\&}, and to the \CPLUSPLUS/
+combinations \.{...}, \.{::}, \.{.*} and \.{->*}.
+The compound assignment operators (e.g., \.{+=}) are
+treated as separate tokens.
+
+@d compress(c) if (loc++<=limit) return(c)
+
+@<Compress tw...@>=
+switch(c) {
+ case '+': if (*loc=='+') compress(plus_plus); break;
+ case '-': if (*loc=='-') {compress(minus_minus);}
+ else if (*loc=='>') if (*(loc+1)=='*') {loc++; compress(minus_gt_ast);}
+ else compress(minus_gt); break;
+ case '.': if (*loc=='*') {compress(period_ast);}
+ else if (*loc=='.' && *(loc+1)=='.') {
+ loc++; compress(dot_dot_dot);
+ }
+ break;
+ case ':': if (*loc==':') compress(colon_colon); break;
+ case '=': if (*loc=='=') compress(eq_eq); break;
+ case '>': if (*loc=='=') {compress(gt_eq);}
+ else if (*loc=='>') compress(gt_gt); break;
+ case '<': if (*loc=='=') {compress(lt_eq);}
+ else if (*loc=='<') compress(lt_lt); break;
+ case '&': if (*loc=='&') compress(and_and); break;
+ case '|': if (*loc=='|') compress(or_or); break;
+ case '!': if (*loc=='=') compress(not_eq); break;
+}
+
+@ @<Get an identifier@>= {
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
+ id_loc=loc; return(identifier);
+}
+
+@ @<Get a constant@>= {
+ id_first=loc-1;
+ if (*id_first=='.' && !xisdigit(*loc)) goto mistake; /* not a constant */
+ if (*id_first=='0') {
+ if (*loc=='x' || *loc=='X') { /* hex constant */
+ loc++; while (xisxdigit(*loc)) loc++; goto found;
+ }
+ }
+ while (xisdigit(*loc)) loc++;
+ if (*loc=='.') {
+ loc++;
+ while (xisdigit(*loc)) loc++;
+ }
+ if (*loc=='e' || *loc=='E') { /* float constant */
+ if (*++loc=='+' || *loc=='-') loc++;
+ while (xisdigit(*loc)) loc++;
+ }
+ found: while (*loc=='u' || *loc=='U' || *loc=='l' || *loc=='L'
+ || *loc=='f' || *loc=='F') loc++;
+ id_loc=loc;
+ return(constant);
+}
+
+@ \CEE/ strings and character constants, delimited by double and single
+quotes, respectively, can contain newlines or instances of their own
+delimiters if they are protected by a backslash. We follow this
+convention, but do not allow the string to be longer than |longest_name|.
+
+@<Get a string@>= {
+ char delim = c; /* what started the string */
+ id_first = section_text+1;
+ id_loc = section_text; *++id_loc=delim;
+ if (delim=='L') { /* wide character constant */
+ delim=*loc++; *++id_loc=delim;
+ }
+ while (1) {
+ if (loc>=limit) {
+ if(*(limit-1)!='\\') {
+ err_print("! String didn't end"); loc=limit; break;
+@.String didn't end@>
+ }
+ if(get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer; break;
+@.Input ended in middle of string@>
+ }
+ else if (++id_loc<=section_text_end) *id_loc='\n'; /* will print as
+ \.{"\\\\\\n"} */
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=section_text_end) *id_loc=c;
+ break;
+ }
+ if (c=='\\') {
+ if (loc>=limit) continue;
+ if (++id_loc<=section_text_end) *id_loc = '\\';
+ c=*loc++;
+ }
+ if (++id_loc<=section_text_end) *id_loc=c;
+ }
+ if (id_loc>=section_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ term_write(section_text+1,25);
+ err_print("...");
+ }
+ id_loc++;
+ return(string);
+}
+
+@ After an \.{@@} sign has been scanned, the next character tells us
+whether there is more work to do.
+
+@<Get control code and possible section name@>= {
+ c=ccode[(eight_bits)*loc++];
+ switch(c) {
+ case ignore: continue;
+ case translit_code: err_print("! Use @@l in limbo only"); continue;
+@.Use @@l in limbo...@>
+ case control_text: while ((c=skip_ahead())=='@@');
+ /* only \.{@@@@} and \.{@@>} are expected */
+ if (*(loc-1)!='>')
+ err_print("! Double @@ should be used in control text");
+@.Double @@ should be used...@>
+ continue;
+ case section_name:
+ cur_section_name_char=*(loc-1);
+ @<Scan the section name and make |cur_section_name| point to it@>;
+ case string: @<Scan a verbatim string@>;
+ case ord: @<Scan an ASCII constant@>;
+ default: return(c);
+ }
+}
+
+@ After scanning a valid ASCII constant that follows
+\.{@@'}, this code plows ahead until it finds the next single quote.
+(Special care is taken if the quote is part of the constant.)
+Anything after a valid ASCII constant is ignored;
+thus, \.{@@'\\nopq'} gives the same result as \.{@@'\\n'}.
+
+@<Scan an ASCII constant@>=
+ id_first=loc;
+ if (*loc=='\\') {
+ if (*++loc=='\'') loc++;
+ }
+ while (*loc!='\'') {
+ if (*loc=='@@') {
+ if (*(loc+1)!='@@')
+ err_print("! Double @@ should be used in ASCII constant");
+@.Double @@ should be used...@>
+ else loc++;
+ }
+ loc++;
+ if (loc>limit) {
+ err_print("! String didn't end"); loc=limit-1; break;
+@.String didn't end@>
+ }
+ }
+ loc++;
+ return(ord);
+
+@ @<Scan the section name...@>= {
+ char *k; /* pointer into |section_text| */
+ @<Put section name into |section_text|@>;
+ if (k-section_text>3 && strncmp(k-2,"...",3)==0)
+ cur_section_name=section_lookup(section_text+1,k-3,1); /* 1 means is a prefix */
+ else cur_section_name=section_lookup(section_text+1,k,0);
+ if (cur_section_name_char=='(')
+ @<If it's not there, add |cur_section_name| to the output file stack, or
+ complain we're out of room@>;
+ return(section_name);
+}
+
+@ Section names are placed into the |section_text| array with consecutive spaces,
+tabs, and carriage-returns replaced by single spaces. There will be no
+spaces at the beginning or the end. (We set |section_text[0]=' '| to facilitate
+this, since the |section_lookup| routine uses |section_text[1]| as the first
+character of the name.)
+
+@<Set init...@>=section_text[0]=' ';
+
+@ @<Put section name...@>=
+k=section_text;
+while (1) {
+ if (loc>limit && get_line()==0) {
+ err_print("! Input ended in section name");
+@.Input ended in section name@>
+ loc=buffer+1; break;
+ }
+ c=*loc;
+ @<If end of name or erroneous nesting, |break|@>;
+ loc++; if (k<section_text_end) k++;
+ if (xisspace(c)) {
+ c=' '; if (*(k-1)==' ') k--;
+ }
+*k=c;
+}
+if (k>=section_text_end) {
+ printf("\n! Section name too long: ");
+@.Section name too long@>
+ term_write(section_text+1,25);
+ printf("..."); mark_harmless;
+}
+if (*k==' ' && k>section_text) k--;
+
+@ @<If end of name or erroneous nesting,...@>=
+if (c=='@@') {
+ c=*(loc+1);
+ if (c=='>') {
+ loc+=2; break;
+ }
+ if (ccode[(eight_bits)c]==new_section) {
+ err_print("! Section name didn't end"); break;
+@.Section name didn't end@>
+ }
+ if (ccode[(eight_bits)c]==section_name) {
+ err_print("! Nesting of section names not allowed"); break;
+@.Nesting of section names...@>
+ }
+ *(++k)='@@'; loc++; /* now |c==*loc| again */
+}
+
+@ At the present point in the program we
+have |*(loc-1)==string|; we set |id_first| to the beginning
+of the string itself, and |id_loc| to its ending-plus-one location in the
+buffer. We also set |loc| to the position just after the ending delimiter.
+
+@<Scan a verbatim string@>= {
+ id_first=loc++; *(limit+1)='@@'; *(limit+2)='>';
+ while (*loc!='@@' || *(loc+1)!='>') loc++;
+ if (loc>=limit) err_print("! Verbatim string didn't end");
+@.Verbatim string didn't end@>
+ id_loc=loc; loc+=2;
+ return(string);
+}
+
+@* Scanning a macro definition.
+The rules for generating the replacement texts corresponding to macros and
+\CEE/ texts of a section are almost identical; the only differences are that
+
+\yskip \item{a)}Section names are not allowed in macros;
+in fact, the appearance of a section name terminates such macros and denotes
+the name of the current section.
+
+\item{b)}The symbols \.{@@d} and \.{@@f} and \.{@@c} are not allowed after
+section names, while they terminate macro definitions.
+
+\item{c)}Spaces are inserted after right parentheses in macros, because the
+ANSI \CEE/ preprocessor sometimes requires it.
+
+\yskip Therefore there is a single procedure |scan_repl| whose parameter
+|t| specifies either |macro| or |section_name|. After |scan_repl| has
+acted, |cur_text| will point to the replacement text just generated, and
+|next_control| will contain the control code that terminated the activity.
+
+@d macro 0
+@d app_repl(c) {if (tok_ptr==tok_mem_end) overflow("token"); *tok_ptr++=c;}
+
+@<Global...@>=
+text_pointer cur_text; /* replacement text formed by |scan_repl| */
+eight_bits next_control;
+
+@ @c
+void
+scan_repl(t) /* creates a replacement text */
+eight_bits t;
+{
+ sixteen_bits a; /* the current token */
+ if (t==section_name) {@<Insert the line number into |tok_mem|@>;}
+ while (1) switch (a=get_next()) {
+ @<In cases that |a| is a non-|char| token (|identifier|,
+ |section_name|, etc.), either process it and change |a| to a byte
+ that should be stored, or |continue| if |a| should be ignored,
+ or |goto done| if |a| signals the end of this replacement text@>@;
+ case ')': app_repl(a);
+ if (t==macro) app_repl(' ');
+ break;
+ default: app_repl(a); /* store |a| in |tok_mem| */
+ }
+ done: next_control=(eight_bits) a;
+ if (text_ptr>text_info_end) overflow("text");
+ cur_text=text_ptr; (++text_ptr)->tok_start=tok_ptr;
+}
+
+@ Here is the code for the line number: first a |sixteen_bits| equal
+to |0150000|; then the numeric line number; then a pointer to the
+file name.
+
+@<Insert the line...@>=
+store_two_bytes(0150000);
+if (changing) id_first=change_file_name;
+else id_first=cur_file_name;
+id_loc=id_first+strlen(id_first);
+if (changing) store_two_bytes((sixteen_bits)change_line);
+else store_two_bytes((sixteen_bits)cur_line);
+{int a=id_lookup(id_first,id_loc,0)-name_dir; app_repl((a / 0400)+0200);
+ app_repl(a % 0400);}
+
+@ @<In cases that |a| is...@>=
+case identifier: a=id_lookup(id_first,id_loc,0)-name_dir;
+ app_repl((a / 0400)+0200);
+ app_repl(a % 0400); break;
+case section_name: if (t!=section_name) goto done;
+ else {
+ @<Was an `@@' missed here?@>;
+ a=cur_section_name-name_dir;
+ app_repl((a / 0400)+0250);
+ app_repl(a % 0400);
+ @<Insert the line number into |tok_mem|@>; break;
+ }
+case output_defs_code: if (t!=section_name) err_print("! Misplaced @@h");
+@.Misplaced @@h@>
+ else {
+ output_defs_seen=1;
+ a=output_defs_flag;
+ app_repl((a / 0400)+0200);
+ app_repl(a % 0400);
+ @<Insert the line number into |tok_mem|@>;
+ }
+ break;
+case constant: case string:
+ @<Copy a string or verbatim construction or numerical constant@>;
+case ord:
+ @<Copy an ASCII constant@>;
+case definition: case format_code: case begin_C: if (t!=section_name) goto done;
+ else {
+ err_print("! @@d, @@f and @@c are ignored in C text"); continue;
+@.@@d, @@f and @@c are ignored in C text@>
+ }
+case new_section: goto done;
+
+@ @<Was an `@@'...@>= {
+ char *try_loc=loc;
+ while (*try_loc==' ' && try_loc<limit) try_loc++;
+ if (*try_loc=='+' && try_loc<limit) try_loc++;
+ while (*try_loc==' ' && try_loc<limit) try_loc++;
+ if (*try_loc=='=') err_print ("! Missing `@@ ' before a named section");
+@.Missing `@@ '...@>
+ /* user who isn't defining a section should put newline after the name,
+ as explained in the manual */
+}
+
+@ @<Copy a string...@>=
+ app_repl(a); /* |string| or |constant| */
+ while (id_first < id_loc) { /* simplify \.{@@@@} pairs */
+ if (*id_first=='@@') {
+ if (*(id_first+1)=='@@') id_first++;
+ else err_print("! Double @@ should be used in string");
+@.Double @@ should be used...@>
+ }
+ app_repl(*id_first++);
+ }
+ app_repl(a); break;
+
+@ This section should be rewritten on machines that don't use ASCII
+code internally.
+@^ASCII code dependencies@>
+
+@<Copy an ASCII constant@>= {
+ int c=(eight_bits) *id_first;
+ if (c=='\\') {
+ c=*++id_first;
+ if (c>='0' && c<='7') {
+ c-='0';
+ if (*(id_first+1)>='0' && *(id_first+1)<='7') {
+ c=8*c+*(++id_first) - '0';
+ if (*(id_first+1)>='0' && *(id_first+1)<='7' && c<32)
+ c=8*c+*(++id_first)- '0';
+ }
+ }
+ else switch (c) {
+ case 't':c='\t';@+break;
+ case 'n':c='\n';@+break;
+ case 'b':c='\b';@+break;
+ case 'f':c='\f';@+break;
+ case 'v':c='\v';@+break;
+ case 'r':c='\r';@+break;
+ case 'a':c='\7';@+break;
+ case '?':c='?';@+break;
+ case 'x':
+ if (xisdigit(*(id_first+1))) c=*(++id_first)-'0';
+ else if (xisxdigit(*(id_first+1))) {
+ ++id_first;
+ c=toupper(*id_first)-'A'+10;
+ }
+ if (xisdigit(*(id_first+1))) c=16*c+*(++id_first)-'0';
+ else if (xisxdigit(*(id_first+1))) {
+ ++id_first;
+ c=16*c+toupper(*id_first)-'A'+10;
+ }
+ break;
+ case '\\':c='\\';@+break;
+ case '\'':c='\'';@+break;
+ case '\"':c='\"';@+break;
+ default: err_print("! Unrecognized escape sequence");
+@.Unrecognized escape sequence@>
+ }
+ }@/
+ /* at this point |c| should have been converted to its ASCII code number */
+ app_repl(constant);
+ if (c>=100) app_repl('0'+c/100);
+ if (c>=10) app_repl('0'+(c/10)%10);
+ app_repl('0'+c%10);
+ app_repl(constant);
+}
+break;
+
+@* Scanning a section.
+The |scan_section| procedure starts when `\.{@@\ }' or `\.{@@*}' has been
+sensed in the input, and it proceeds until the end of that section. It
+uses |section_count| to keep track of the current section number; with luck,
+\.{CWEAVE} and \.{CTANGLE} will both assign the same numbers to sections.
+
+@<Global...@>=
+extern sixteen_bits section_count; /* the current section number */
+
+@ The body of |scan_section| is a loop where we look for control codes
+that are significant to \.{CTANGLE}: those
+that delimit a definition, the \CEE/ part of a module, or a new module.
+
+@c
+void
+scan_section()
+{
+ name_pointer p; /* section name for the current section */
+ text_pointer q; /* text for the current section */
+ sixteen_bits a; /* token for left-hand side of definition */
+ section_count++; @+ no_where=1;
+ if (*(loc-1)=='*' && show_progress) { /* starred section */
+ printf("*%d",section_count); update_terminal;
+ }
+ next_control=0;
+ while (1) {
+ @<Skip ahead until |next_control| corresponds to \.{@@d}, \.{@@<},
+ \.{@@\ } or the like@>;
+ if (next_control == definition) { /* \.{@@d} */
+ @<Scan a definition@>@;
+ continue;
+ }
+ if (next_control == begin_C) { /* \.{@@c} or \.{@@p} */
+ p=name_dir; break;
+ }
+ if (next_control == section_name) { /* \.{@@<} or \.{@@(} */
+ p=cur_section_name;
+ @<If section is not being defined, |continue| @>;
+ break;
+ }
+ return; /* \.{@@\ } or \.{@@*} */
+ }
+ no_where=print_where=0;
+ @<Scan the \CEE/ part of the current section@>;
+}
+
+@ At the top of this loop, if |next_control==section_name|, the
+section name has already been scanned (see |@<Get control code
+and...@>|). Thus, if we encounter |next_control==section_name| in the
+skip-ahead process, we should likewise scan the section name, so later
+processing will be the same in both cases.
+
+@<Skip ahead until |next_control| ...@>=
+while (next_control<definition)
+ /* |definition| is the lowest of the ``significant'' codes */
+ if((next_control=skip_ahead())==section_name){
+ loc-=2; next_control=get_next();
+ }
+
+@ @<Scan a definition@>= {
+ while ((next_control=get_next())=='\n'); /*allow newline before definition */
+ if (next_control!=identifier) {
+ err_print("! Definition flushed, must start with identifier");
+@.Definition flushed...@>
+ continue;
+ }
+ app_repl(((a=id_lookup(id_first,id_loc,0)-name_dir) / 0400)+0200);
+ /* append the lhs */
+ app_repl(a % 0400);
+ if (*loc!='(') { /* identifier must be separated from replacement text */
+ app_repl(string); app_repl(' '); app_repl(string);
+ }
+ scan_repl(macro);
+ cur_text->text_link=0; /* |text_link==0| characterizes a macro */
+}
+
+@ If the section name is not followed by \.{=} or \.{+=}, no \CEE/
+code is forthcoming: the section is being cited, not being
+defined. This use is illegal after the definition part of the
+current section has started, except inside a comment, but
+\.{CTANGLE} does not enforce this rule; it simply ignores the offending
+section name and everything following it, up to the next significant
+control code.
+
+@<If section is not being defined, |continue| @>=
+while ((next_control=get_next())=='+'); /* allow optional \.{+=} */
+if (next_control!='=' && next_control!=eq_eq)
+ continue;
+
+@ @<Scan the \CEE/...@>=
+@<Insert the section number into |tok_mem|@>;
+scan_repl(section_name); /* now |cur_text| points to the replacement text */
+@<Update the data structure so that the replacement text is accessible@>;
+
+@ @<Insert the section number...@>=
+store_two_bytes((sixteen_bits)(0150000+section_count));
+ /* |0150000==0320*0400| */
+
+@ @<Update the data...@>=
+if (p==name_dir||p==0) { /* unnamed section, or bad section name */
+ (last_unnamed)->text_link=cur_text-text_info; last_unnamed=cur_text;
+}
+else if (p->equiv==(char *)text_info) p->equiv=(char *)cur_text;
+ /* first section of this name */
+else {
+ q=(text_pointer)p->equiv;
+ while (q->text_link<section_flag)
+ q=q->text_link+text_info; /* find end of list */
+ q->text_link=cur_text-text_info;
+}
+cur_text->text_link=section_flag;
+ /* mark this replacement text as a nonmacro */
+
+@ @<Predec...@>=
+void phase_one();
+
+@ @c
+void
+phase_one() {
+ phase=1;
+ section_count=0;
+ reset_input();
+ skip_limbo();
+ while (!input_has_ended) scan_section();
+ check_complete();
+ phase=2;
+}
+
+@ Only a small subset of the control codes is legal in limbo, so limbo
+processing is straightforward.
+
+@<Predecl...@>=
+void skip_limbo();
+
+@ @c
+void
+skip_limbo()
+{
+ char c;
+ while (1) {
+ if (loc>limit && get_line()==0) return;
+ *(limit+1)='@@';
+ while (*loc!='@@') loc++;
+ if (loc++<=limit) {
+ c=*loc++;
+ if (ccode[(eight_bits)c]==new_section) break;
+ switch (ccode[(eight_bits)c]) {
+ case translit_code: @<Read in transliteration of a character@>; break;
+ case format_code: case '@@': break;
+ case control_text: if (c=='q' || c=='Q') {
+ while ((c=skip_ahead())=='@@');
+ if (*(loc-1)!='>')
+ err_print("! Double @@ should be used in control text");
+@.Double @@ should be used...@>
+ break;
+ } /* otherwise fall through */
+ default: err_print("! Double @@ should be used in limbo");
+@.Double @@ should be used...@>
+ }
+ }
+ }
+}
+
+@ @<Read in transliteration of a character@>=
+ while(xisspace(*loc)&&loc<limit) loc++;
+ loc+=3;
+ if (loc>limit || !xisxdigit(*(loc-3)) || !xisxdigit(*(loc-2)) @|
+ || (*(loc-3)>='0' && *(loc-3)<='7') || !xisspace(*(loc-1)))
+ err_print("! Improper hex number following @@l");
+@.Improper hex number...@>
+ else {
+ unsigned i;
+ char *beg;
+ sscanf(loc-3,"%x",&i);
+ while(xisspace(*loc)&&loc<limit) loc++;
+ beg=loc;
+ while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_')) loc++;
+ if (loc-beg>=translit_length)
+ err_print("! Replacement string in @@l too long");
+@.Replacement string in @@l...@>
+ else{
+ strncpy(translit[i-0200],beg,loc-beg);
+ translit[i-0200][loc-beg]='\0';
+ }
+ }
+
+@ Because on some systems the difference between two pointers is a |long|
+but not an |int|, we use \.{\%ld} to print these quantities.
+
+@c
+void
+print_stats() {
+ printf("\nMemory usage statistics:\n");
+ printf("%ld names (out of %ld)\n",
+ (long)(name_ptr-name_dir),(long)max_names);
+ printf("%ld replacement texts (out of %ld)\n",
+ (long)(text_ptr-text_info),(long)max_texts);
+ printf("%ld bytes (out of %ld)\n",
+ (long)(byte_ptr-byte_mem),(long)max_bytes);
+ printf("%ld tokens (out of %ld)\n",
+ (long)(tok_ptr-tok_mem),(long)max_toks);
+}
+
+@** Index.
+Here is a cross-reference table for \.{CTANGLE}.
+All sections in which an identifier is
+used are listed with that identifier, except that reserved words are
+indexed only when they appear in format definitions, and the appearances
+of identifiers in section names are not indexed. Underlined entries
+correspond to where the identifier was declared. Error messages and
+a few other things like ``ASCII code dependencies'' are indexed here too.
diff --git a/Build/source/texk/web2c/cwebdir/cweav-bs.ch b/Build/source/texk/web2c/cwebdir/cweav-bs.ch
new file mode 100644
index 00000000000..186d4cc777c
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-bs.ch
@@ -0,0 +1,302 @@
+Changes for CWEAVE for MSDOS and Borland C++ 3.1 using the following
+options (and perhaps others):
+
+ -mc -w-pro -Ff=5000 -Z- -O-p
+
+The options -Z- and -O-p explicitly turn off optimizations that break
+the code. (See makefile.bs.)
+
+The main purpose of these changes is to support MSDOS with full-size arrays
+by using "huge" pointers.
+
+This file contributed by Barry Schwartz, trashman@crud.mn.org, 28 Jun 94.
+(Includes workaround for compiler bug [pointers wrapping around at
+ segment boundaries], November 1993, contributed by Jorge Fernandez Arnaiz
+ -- arnaiz@redvax1.dgsca.unam.mx)
+(Last revised 5 Dec 94 with help of bob@microprograms.com.)
+
+
+@x Section 1.
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE (Version 3.64pc/big)\n"
+@z
+
+
+@x Section 9.
+@d chunk_marker 0
+
+@<Common code...@>=
+typedef struct name_info {
+ char *byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ } dummy;
+ char *equiv_or_xref; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char byte_mem[]; /* characters of names */
+extern char *byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char *byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@y
+@d chunk_marker 0
+
+@f huge extern
+
+@<Common code...@>=
+typedef struct name_info {
+ char huge* byte_start; /* beginning of the name in |byte_mem| */
+ struct name_info *link;
+ union {
+ struct name_info *Rlink; /* right link in binary search tree for section
+ names */
+ char Ilk; /* used by identifiers in \.{CWEAVE} only */
+ } dummy;
+ union {
+ char *equiv_member;
+ char huge* xref_member;
+ } ptr_union; /* info corresponding to names */
+} name_info; /* contains information about an identifier or section name */
+typedef name_info *name_pointer; /* pointer into array of \&{name\_info}s */
+typedef name_pointer *hash_pointer;
+extern char huge byte_mem[]; /* characters of names */
+extern char huge* byte_mem_end; /* end of |byte_mem| */
+extern name_info name_dir[]; /* information about names */
+extern name_pointer name_dir_end; /* end of |name_dir| */
+extern name_pointer name_ptr; /* first unused position in |byte_start| */
+extern char huge* byte_ptr; /* first unused position in |byte_mem| */
+extern name_pointer hash[]; /* heads of hash lists */
+extern hash_pointer hash_end; /* end of |hash| */
+extern hash_pointer h; /* index into hash-head array */
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@z
+
+
+@x Section 18.
+typedef struct xref_info {
+ sixteen_bits num; /* section number plus zero or |def_flag| */
+ struct xref_info *xlink; /* pointer to the previous cross-reference */
+} xref_info;
+typedef xref_info *xref_pointer;
+@y
+typedef struct xref_info {
+ sixteen_bits num; /* section number plus zero or |def_flag| */
+ struct xref_info huge* xlink; /* pointer to the previous cross-reference */
+} xref_info;
+typedef xref_info huge* xref_pointer;
+@z
+
+
+@x Section 19.
+xref_info xmem[max_refs]; /* contains cross-reference information */
+xref_pointer xmem_end = xmem+max_refs-1;
+@y
+xref_info huge xmem[max_refs]; /* contains cross-reference information */
+xref_pointer xmem_end;
+@z
+
+
+@x Section 20.
+@d xref equiv_or_xref
+@y
+@d xref ptr_union.xref_member
+@z
+
+
+@x Section 20.
+xref_ptr=xmem; name_dir->xref=(char*)xmem; xref_switch=0; section_xref_switch=0;
+xmem->num=0; /* sentinel value */
+@y
+xmem_end = xmem + max_refs - 1;
+xref_ptr=xmem; name_dir->xref=(char*)xmem; xref_switch=0; section_xref_switch=0;
+xmem->num=0; /* sentinel value */
+@z
+
+
+@x Section 21.
+ append_xref(m); xref_ptr->xlink=q; p->xref=(char*)xref_ptr;
+@y
+ append_xref(m); xref_ptr->xlink=q; p->xref=(char huge*)xref_ptr;
+@z
+
+
+@x Section 22.
+ if (r==xmem) p->xref=(char*)xref_ptr;
+@y
+ if (r==xmem) p->xref=(char huge*)xref_ptr;
+@z
+
+
+@x Section 23.
+ q=(xref_pointer)p->xref;
+ if (q->num==file_flag) return;
+ append_xref(file_flag);
+ xref_ptr->xlink = q;
+ p->xref = (char *)xref_ptr;
+@y
+ q=(xref_pointer)p->xref;
+ if (q->num==file_flag) return;
+ append_xref(file_flag);
+ xref_ptr->xlink = q;
+ p->xref = (char huge*)xref_ptr;
+@z
+
+@x Section 25. (to please Borland's C++, version 4.02)
+token tok_mem[max_toks]; /* tokens */
+token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */
+token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
+token_pointer tok_ptr; /* first unused position in |tok_mem| */
+text_pointer text_ptr; /* first unused position in |tok_start| */
+text_pointer tok_start_end = tok_start+max_texts-1; /* end of |tok_start| */
+token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
+@y
+token tok_mem[max_toks]; /* tokens */
+token_pointer tok_mem_end; /* end of |tok_mem| */
+token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
+token_pointer tok_ptr; /* first unused position in |tok_mem| */
+text_pointer text_ptr; /* first unused position in |tok_start| */
+text_pointer tok_start_end; /* end of |tok_start| */
+token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
+@z
+
+@x Section 26. (goes with the previous change)
+tok_start[1]=tok_mem+1;
+max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
+@y
+tok_start[1]=tok_mem+1;
+tok_mem_end=tok_mem+max_toks-1;
+tok_start_end=tok_start+max_texts-1;
+max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
+@z
+
+
+@x Section 27.
+ p->ilk=t; p->xref=(char*)xmem;
+@y
+ p->ilk=t; p->xref=(char huge*)xmem;
+@z
+
+
+@x Section 27.
+ p->xref=(char*)xmem;
+@y
+ p->xref=(char huge*)xmem;
+@z
+
+
+@x Section 70.
+ if (unindexed(lhs)) { /* retain only underlined entries */
+ xref_pointer q,r=NULL;
+ for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)
+ if (q->num<def_flag)
+ if (r) r->xlink=q->xlink;
+ else lhs->xref=(char*)q->xlink;
+ else r=q;
+ }
+@y
+ if (unindexed(lhs)) { /* retain only underlined entries */
+ xref_pointer q,r=NULL;
+ for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)
+ if (q->num<def_flag)
+ if (r) r->xlink=q->xlink;
+ else lhs->xref=(char huge*)q->xlink;
+ else r=q;
+ }
+@z
+
+
+@x Section 87.
+ char *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
+ out('{');
+ for (k=p->byte_start; k<k_end; k++) {
+@y
+ char huge* k, huge* k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
+ out('{');
+ for (k=p->byte_start; k<k_end; k++) {
+@z
+
+
+@x Section 116.
+ append_xref(0); /* this number doesn't matter */
+ xref_ptr->xlink=(xref_pointer)p->xref; r=xref_ptr;
+ p->xref=(char*)xref_ptr;
+ while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
+ r->num=m; /* everything from |q| on is left undisturbed */
+@y
+ append_xref(0); /* this number doesn't matter */
+ xref_ptr->xlink=(xref_pointer)p->xref; r=xref_ptr;
+ p->xref=(char huge*)xref_ptr;
+ while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
+ r->num=m; /* everything from |q| on is left undisturbed */
+@z
+
+
+@x Section 163.
+@ @<Change |pp| to $\max...@>=
+@y
+@ @<Change |pp| to $\max...@>=
+#ifdef __MSDOS__
+if (d<0 && pp+d>pp) pp=scrap_base; /* segmented architecture caused wrap */
+else
+#endif
+@z
+
+
+@x Section 194.
+ char *p; /* index into |byte_mem| */
+@y
+ char huge *p; /* index into |byte_mem| */
+@z
+
+
+@x Section 229.
+ if (cur_name->xref!=(char*)xmem) {
+@y
+ if (cur_name->xref!=(char huge*)xmem) {
+@z
+
+
+@x Section 232.
+char *cur_byte; /* index into |byte_mem| */
+@y
+char huge* cur_byte; /* index into |byte_mem| */
+@z
+
+
+@x Section 241.
+switch (cur_name->ilk) {
+ case normal: if (is_tiny(cur_name)) out_str("\\|");
+ else {char *j;
+@y
+switch (cur_name->ilk) {
+ case normal: if (is_tiny(cur_name)) out_str("\\|");
+ else {char huge* j;
+@z
+
+
+@x Section 241.
+ case custom: case quoted: {char *j; out_str("$\\");
+@y
+ case custom: case quoted: {char huge* j; out_str("$\\");
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweav-man.ch b/Build/source/texk/web2c/cwebdir/cweav-man.ch
new file mode 100644
index 00000000000..6cfcc8fe2d2
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-man.ch
@@ -0,0 +1,22 @@
+Change file to help make Appendix F of the full CWEB manual
+@x
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+@y
+\def\botofcontents{\vfill\titlefalse}
+\def\contentspagenumber{109}
+\def\title{APPENDIX F: CWEAVE}
+\let\K=\leftarrow
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweav-pc.ch b/Build/source/texk/web2c/cwebdir/cweav-pc.ch
new file mode 100644
index 00000000000..28cd94f5a3f
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-pc.ch
@@ -0,0 +1,39 @@
+This is the change file for CWEB's CWEAVE under DOS
+(Contributed by Lee Wittenberg, March 1993)
+(Also includes workaround for compiler bug, November 1993,
+ contributed by Jorge Fernandez Arnaiz -- arnaiz@redvax1.dgsca.unam.mx)
+
+Changes necessary for compiling with Borland C/C++
+Use compilation switches -mc -w-pro -Ff=5000
+
+Note: The changes to section 4 are not necessary if using a compiler
+that allows >64K arrays. (If you need lots more bytes, try the alternate
+change files that have -bs in their name instead of -pc.)
+
+@x section 1
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+@d banner "This is CWEAVE (Version 3.64pc)\n"
+@z
+
+@x section 4
+@d max_bytes 90000 /* the number of bytes in identifiers,
+@y
+@d max_bytes (unsigned)60000 /* the number of bytes in identifiers,
+@z
+@x
+@d max_refs 20000 /* number of cross-references; must be less than 65536 */
+@y
+@d max_refs 10000 /* number of cross-references; must be less than 65536 */
+@z
+
+@x section 163
+@ @<Change |pp| to $\max...@>=
+@y
+@ @<Change |pp| to $\max...@>=
+#ifdef __MSDOS__
+if (d<0 && pp+d>pp) pp=scrap_base; /* segmented architecture caused wrap */
+else
+#endif
+@z
+
diff --git a/Build/source/texk/web2c/cwebdir/cweav-ql.ch b/Build/source/texk/web2c/cwebdir/cweav-ql.ch
new file mode 100644
index 00000000000..3e37ba23522
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-ql.ch
@@ -0,0 +1,32 @@
+This is the change file for CWEB's CWEAVE under QDOS/SMSQ
+(Contributed by Robert H. Klein, September 1994)
+
+This change file is intended for use with C68 v4.14 (or later).
+compile with
+ex <dev_>cc;"-v -h -c =500000 cweave_c"
+
+
+@x
+\def\title{CWEAVE (Version 3.64)}
+@y
+\def\title{CWEAVE (QL Version 3.64)}
+@z
+
+@x section 1
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+@d banner "This is CWEAVE (QL Version 3.64)\n"
+@z
+
+@x
+@i common.h
+@y
+@i common_h
+@z
+
+
+@x
+@i prod.w
+@y
+@i prod_w
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweav-vms.ch b/Build/source/texk/web2c/cwebdir/cweav-vms.ch
new file mode 100644
index 00000000000..b6f46559cc5
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-vms.ch
@@ -0,0 +1,37 @@
+This is the change file for CWEB's CWEAVE for VAX/VMS.
+
+created:
+ 1991 JM (John Mulhollen, Science Applications International Corporation)
+
+modified:
+ 01-FEB-1992 ST (Stephan Trebels <trebels@ams02.dnet.gwdg.de>)
+ > include ctype,stdio from textlibrary SYS$SHARE:VAXCDEF.TLB
+ > change banner line to include (VAX/VMS)
+ > allow $ in identifiers (*necessary* for VAX/VMS)
+ ? will someone eventally make a CLD interface? (should be easy)
+
+(also modified by Don Knuth to keep version numbers uptodate)
+
+@x section 1 (01-FEB-1992 ST)
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+@d banner "This is CWEAVE (VAX/VMS Version 3.64)\n"
+@z
+
+@x section 6 (from common.h) (01-FEB-1992 ST)
+#include <stdio.h>
+@y
+#include stdio /* VMS searches Textlibraries faster */
+@z
+
+@x section 38 (1991 JM) (01-FEB-1992 ST)
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+@y
+#include ctype /* VMS searches Textlibraries faster */
+@z
+
+@x section 39 (01-FEB-1992 ST)
+@d isxalpha(c) ((c)=='_') /* non-alpha character allowed in identifier */
+@y
+@d isxalpha(c) ((c)=='_' || (c)=='$') /* non-alpha characters allowed in id */
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweav-w2c.ch b/Build/source/texk/web2c/cwebdir/cweav-w2c.ch
new file mode 100644
index 00000000000..59552eedcda
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-w2c.ch
@@ -0,0 +1,768 @@
+% Kpathsea changes for CWEB by Wlodek Bzyl and Olaf Weber
+% Copyright 2002 Wlodek Bzyl and Olaf Weber
+% This file is in the Public Domain.
+
+
+@x l.32
+\def\title{CWEAVE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+@y
+\def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}}
+\def\SQUARE{\vrule width 2pt depth -1pt height 3pt}
+\def\sqitem{\item{\SQUARE}}
+
+\def\title{CWEAVE (Version 3.64k)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64k)}
+ \vfill}
+@z
+
+This change can not be applied when `tie' is used
+(TOC file can not be typeset).
+
+%@x l.51
+%\let\maybe=\iftrue
+%@y
+%\let\maybe=\iffalse % print only changed modules
+%@z
+
+
+Section 1.
+
+@x l.65
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE, Version 3.64"
+@z
+
+
+Section 2.
+
+@x l.77
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
+
+Section 3.
+
+@x l.98
+int main (ac, av)
+int ac; /* argument count */
+char **av; /* argument values */
+@y
+int main P2C(int,ac, char**,av)
+@z
+
+@x l.107 - Add Web2C version to banner.
+ if (show_banner) printf(banner); /* print a ``banner line'' */
+@y
+ if (show_banner) {
+ printf("%s%s\n", banner, versionstring); /* print a ``banner line'' */
+ }
+@z
+
+
+Section 5.
+
+@x common.h l.30 - boolean comes from kpathsea.
+typedef short boolean;
+@y
+@z
+
+Section 6.
+
+@x l.36
+#include <stdio.h>
+@y
+#include <stdio.h>
+/* #include "cpascal.h" ??? */
+extern char *versionstring;
+#include <kpathsea/kpathsea.h>
+@z
+
+Section 9.
+
+@x common.h l.109
+extern name_pointer id_lookup(); /* looks up a string in the identifier table */
+extern name_pointer section_lookup(); /* finds section name */
+extern void print_section_name(), sprint_section_name();
+@y
+/* looks up a string in the identifier table */
+extern name_pointer id_lookup P3H(char*,char*,char);
+/* finds section name */
+extern name_pointer section_lookup P3H(char*,char*,char);
+extern void print_section_name P1H(name_pointer);
+extern void sprint_section_name P2H(char*,name_pointer);
+@z
+
+Section 10.
+
+@x common.h l.123 - explicit types.
+extern history; /* indicates how bad this run was */
+extern err_print(); /* print error message and context */
+extern wrap_up(); /* indicate |history| and exit */
+extern void fatal(); /* issue error message and die */
+extern void overflow(); /* succumb because a table has overflowed */
+@y
+extern int history; /* indicates how bad this run was */
+extern void err_print P1H(char*); /* print error message and context */
+extern int wrap_up P1H(void); /* indicate |history| and exit */
+extern void fatal P2H(char*,char*); /* issue error message and die */
+extern void overflow P1H(char*); /* succumb because a table has overflowed */
+@z
+
+Section 11.
+
+@x common.h l.131 - max_file_name_length is way too small.
+@d max_file_name_length 60
+@y
+@d max_file_name_length 1024
+@z
+
+@x common.h l.138 - explicit types.
+extern include_depth; /* current level of nesting */
+@y
+extern int include_depth; /* current level of nesting */
+@z
+
+@x common.h l.148 - explicit types.
+extern line[]; /* number of current line in the stacked files */
+extern change_line; /* number of current line in change file */
+@y
+extern int line[]; /* number of current line in the stacked files */
+extern int change_line; /* number of current line in change file */
+@z
+
+@x common.h l.153 - explicit types.
+extern reset_input(); /* initialize to read the web file and change file */
+extern get_line(); /* inputs the next line */
+extern check_complete(); /* checks that all changes were picked up */
+@y
+extern void reset_input P1H(void); /* initialize to read the web file and change file */
+extern int get_line P1H(void); /* inputs the next line */
+extern void check_complete P1H(void); /* checks that all changes were picked up */
+@z
+
+Section 15.
+
+@x common.h l.192
+extern void common_init();
+@y
+extern void common_init P1H(void);
+@z
+
+Section 21.
+
+@x l.276
+new_xref(p)
+name_pointer p;
+@y
+new_xref P1C(name_pointer,p)
+@z
+
+Section 22.
+
+@x l.307
+new_section_xref(p)
+name_pointer p;
+@y
+new_section_xref P1C(name_pointer,p)
+@z
+
+Section 23.
+
+@x l.327
+set_file_flag(p)
+name_pointer p;
+@y
+set_file_flag P1C(name_pointer,p)
+@z
+
+Section 27.
+
+@x l.371
+int names_match(p,first,l,t)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+int l; /* length of identifier */
+eight_bits t; /* desired ilk */
+@y
+int names_match P4C(name_pointer,p, char*,first, int,l, char,t)
+@z
+
+@x l.383
+init_p(p,t)
+name_pointer p;
+eight_bits t;
+@y
+init_p P2C(name_pointer,p, char,t)
+@z
+
+@x l.391
+init_node(p)
+name_pointer p;
+@y
+init_node P1C(name_pointer,p)
+@z
+
+Section 34.
+
+@x l.600
+void skip_limbo();
+@y
+void skip_limbo P1H(void);
+@z
+
+Section 35.
+
+@x l.604
+skip_limbo() {
+@y
+skip_limbo P1H(void) {
+@z
+
+Section 36.
+
+@x l.626
+skip_TeX() /* skip past pure \TEX/ code */
+@y
+skip_TeX P1H(void) /* skip past pure \TEX/ code */
+@z
+
+Section 38.
+
+@x l.682 - Add declaration for versionstring.
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+@y
+@z
+
+Section 39.
+
+@x l.696
+eight_bits get_next();
+@y
+eight_bits get_next P1H(void);
+@z
+
+Section 40.
+
+@x l.700
+get_next() /* produces the next input token */
+@y
+get_next P1H(void) /* produces the next input token */
+@z
+
+Section 55.
+
+@x l.971
+void skip_restricted();
+@y
+void skip_restricted P1H(void);
+@z
+
+Section 56.
+
+@x l.975
+skip_restricted()
+@y
+skip_restricted P1H(void)
+@z
+
+Section 59.
+
+@x l.1024
+void phase_one();
+@y
+void phase_one P1H(void);
+@z
+
+Section 60.
+
+@x l.1028
+phase_one() {
+@y
+phase_one P1H(void) {
+@z
+
+Section 62.
+
+@x l.1076
+void C_xref();
+@y
+void C_xref P1H(eight_bits);
+@z
+
+Section 63.
+
+@x l.1080
+C_xref( spec_ctrl ) /* makes cross-references for \CEE/ identifiers */
+ eight_bits spec_ctrl;
+@y
+C_xref P1C(eight_bits,spec_ctrl) /* makes cross-references for \CEE/ identifiers */
+@z
+
+Section 64.
+
+@x l.1104
+void outer_xref();
+@y
+void outer_xref P1H(void);
+@z
+
+Section 65.
+
+@x l.1108
+outer_xref() /* extension of |C_xref| */
+@y
+outer_xref P1H(void) /* extension of |C_xref| */
+@z
+
+Section 74.
+
+@x l.1266
+void section_check();
+@y
+void section_check P1H(name_pointer);
+@z
+
+Section 75.
+
+@x l.1270
+section_check(p)
+name_pointer p; /* print anomalies in subtree |p| */
+@y
+section_check P1C(name_pointer,p) /* print anomalies in subtree |p| */
+@z
+
+Section 78.
+
+@x l.1323
+flush_buffer(b,per_cent,carryover)
+char *b; /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */
+boolean per_cent,carryover;
+@y
+flush_buffer P3C(char*,b, boolean,per_cent, boolean,carryover)
+@z
+
+Section 79.
+
+@x l.1352
+finish_line() /* do this at the end of a line */
+@y
+finish_line P1H(void) /* do this at the end of a line */
+@z
+
+Section 81.
+
+@x l.1384
+out_str(s) /* output characters from |s| to end of string */
+char *s;
+@y
+out_str P1C(char*,s) /* output characters from |s| to end of string */
+@z
+
+Section 83.
+
+@x l.1402
+void break_out();
+@y
+void break_out P1H(void);
+@z
+
+Section 84.
+
+@x l.1406
+break_out() /* finds a way to break the output line */
+@y
+break_out P1H(void) /* finds a way to break the output line */
+@z
+
+Section 86.
+
+@x l.1441
+out_section(n)
+sixteen_bits n;
+@y
+out_section P1C(sixteen_bits,n)
+@z
+
+Section 87.
+
+@x l.1455
+out_name(p,quote_xalpha)
+name_pointer p;
+boolean quote_xalpha;
+@y
+out_name P2C(name_pointer,p, boolean,quote_xalpha)
+@z
+
+Section 88.
+
+@x l.1485
+copy_limbo()
+@y
+copy_limbo P1H(void)
+@z
+
+Section 90.
+
+@x l.1520
+copy_TeX()
+@y
+copy_TeX P1H(void)
+@z
+
+Section 91.
+
+@x l.1449
+int copy_comment();
+@y
+int copy_comment P2H(boolean,int);
+@z
+
+Section 92.
+
+@x l.1551
+int copy_comment(is_long_comment,bal) /* copies \TEX/ code in comments */
+boolean is_long_comment; /* is this a traditional \CEE/ comment? */
+int bal; /* brace balance */
+@y
+int copy_comment P2C(boolean,is_long_comment, int,bal)
+@z
+
+Section 99.
+
+@x l.1784
+print_cat(c) /* symbolic printout of a category */
+eight_bits c;
+@y
+print_cat P1C(eight_bits,c)
+@z
+
+Section 106.
+
+@x l.2139
+print_text(p) /* prints a token list for debugging; not used in |main| */
+text_pointer p;
+@y
+print_text P1C(text_pointer,p)
+@z
+
+Section 109.
+
+@x l.2264
+app_str(s)
+char *s;
+@y
+app_str P1C(char*,s)
+@z
+
+@x l.2271
+big_app(a)
+token a;
+@y
+big_app P1C(token,a)
+@z
+
+@x l.2288
+big_app1(a)
+scrap_pointer a;
+@y
+big_app1 P1C(scrap_pointer,a)
+@z
+
+Section 111.
+
+@x l.2415
+find_first_ident(p)
+text_pointer p;
+@y
+find_first_ident P1C(text_pointer,p)
+@z
+
+Section 112.
+
+@x l.2447
+make_reserved(p) /* make the first identifier in |p->trans| like |int| */
+scrap_pointer p;
+@y
+make_reserved P1C(scrap_pointer,p)
+@z
+
+Section 113.
+
+@x l.2478
+make_underlined(p)
+/* underline the entry for the first identifier in |p->trans| */
+scrap_pointer p;
+@y
+make_underlined P1C(scrap_pointer,p)
+@z
+
+Section 114.
+
+@x l.2495
+void underline_xref();
+@y
+void underline_xref P1H(name_pointer);
+@z
+
+Section 115.
+
+@x l.2499
+underline_xref(p)
+name_pointer p;
+@y
+underline_xref P1C(name_pointer,p)
+@z
+
+Section 164.
+
+@x l.3004
+reduce(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+@y
+reduce P5C(scrap_pointer,j, short,k, eight_bits,c, short,d, short,n)
+@z
+
+Section 165.
+
+@x l.3030
+squash(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+@y
+squash P5C(scrap_pointer,j, short,k, eight_bits,c, short,d, short,n)
+@z
+
+Section 170.
+
+@x l.3126
+translate() /* converts a sequence of scraps */
+@y
+translate P1H(void) /* converts a sequence of scraps */
+@z
+
+Section 174.
+
+@x l.3191
+C_parse(spec_ctrl) /* creates scraps from \CEE/ tokens */
+ eight_bits spec_ctrl;
+@y
+C_parse P1C(eight_bits,spec_ctrl) /* creates scraps from \CEE/ tokens */
+@z
+
+Section 181.
+
+@x l.3421
+void app_cur_id();
+@y
+void app_cur_id P1H(boolean);
+@z
+
+Section 182.
+
+@x l.3425
+app_cur_id(scrapping)
+boolean scrapping; /* are we making this into a scrap? */
+@y
+app_cur_id P1C(boolean,scrapping)
+@z
+
+Section 183.
+
+@x l.3451
+C_translate()
+@y
+C_translate P1H(void)
+@z
+
+Section 184.
+
+@x l.3480
+outer_parse() /* makes scraps from \CEE/ tokens and comments */
+@y
+outer_parse P1H(void) /* makes scraps from \CEE/ tokens and comments */
+@z
+
+Section 189.
+
+@x l.3586
+push_level(p) /* suspends the current level */
+text_pointer p;
+@y
+push_level P1C(text_pointer,p) /* suspends the current level */
+@z
+
+Section 190.
+
+@x l.3606
+pop_level()
+@y
+pop_level P1H(void)
+@z
+
+Section 192.
+
+@x l.3628
+get_output() /* returns the next token of output */
+@y
+get_output P1H(void) /* returns the next token of output */
+@z
+
+Section 193.
+
+@x l.3665
+output_C() /* outputs the current token list */
+@y
+output_C P1H(void) /* outputs the current token list */
+@z
+
+Section 194.
+
+@x l.3687
+void make_output();
+@y
+void make_output P1H(void);
+@z
+
+Section 195.
+
+@x l.3691
+make_output() /* outputs the equivalents of tokens */
+@y
+make_output P1H(void) /* outputs the equivalents of tokens */
+@z
+
+Section 205.
+
+@x l.3951
+void phase_two();
+@y
+void phase_two P1H(void);
+@z
+
+Section 206.
+
+@x l.3955
+phase_two() {
+@y
+phase_two P1H(void) {
+@z
+
+Section 212.
+
+@x l.4074
+void finish_C();
+@y
+void finish_C P1H(boolean);
+@z
+
+Section 213.
+
+@x l.4078
+finish_C(visible) /* finishes a definition or a \CEE/ part */
+ boolean visible; /* nonzero if we should produce \TEX/ output */
+@y
+finish_C P1C(boolean,visible) /* finishes a definition or a \CEE/ part */
+@z
+
+Section 221.
+
+@x l.4245
+void footnote();
+@y
+void footnote P1H(sixteen_bits);
+@z
+
+Section 222.
+
+@x l.4249
+footnote(flag) /* outputs section cross-references */
+sixteen_bits flag;
+@y
+footnote P1C(sixteen_bits,flag) /* outputs section cross-references */
+@z
+
+Section 225.
+
+@x l.4294
+void phase_three();
+@y
+void phase_three P1H(void);
+@z
+
+Section 226.
+
+@x l.4298
+phase_three() {
+@y
+phase_three P1H(void) {
+@z
+
+Section 237.
+
+@x l.4474
+void unbucket();
+@y
+void unbucket P1H(eight_bits);
+@z
+
+Section 238.
+
+@x l.4478
+unbucket(d) /* empties buckets having depth |d| */
+eight_bits d;
+@y
+unbucket P1C(eight_bits,d) /* empties buckets having depth |d| */
+@z
+
+Section 246.
+
+@x l.4594
+void section_print();
+@y
+void section_print P1H(name_pointer);
+@z
+
+Section 247.
+
+@x l.4598
+section_print(p) /* print all section names in subtree |p| */
+name_pointer p;
+@y
+section_print P1C(name_pointer,p) /* print all section names in subtree |p| */
+@z
+
+Section 249.
+
+@x l.4620
+print_stats() {
+@y
+print_stats P1H(void) {
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweav-w32.ch b/Build/source/texk/web2c/cwebdir/cweav-w32.ch
new file mode 100644
index 00000000000..26825b0bfd1
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweav-w32.ch
@@ -0,0 +1,52 @@
+This is the change file for CWEB's CWEAVE under Win32
+(Contributed by Fabrice Popineau, February 2002)
+
+@x section 1
+@d banner "This is CWEAVE (Version 3.64)\n"
+@y
+@d banner "This is CWEAVE (Version 3.64win32)\n"
+@z
+
+@x
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+@y
+@z
+
+@x
+int names_match(p,first,l,t)
+name_pointer p; /* points to the proposed match */
+@y
+int __cdecl names_match(p,first,l,t)
+name_pointer p; /* points to the proposed match */
+@z
+
+@x
+void
+init_p(p,t)
+name_pointer p;
+@y
+void __cdecl
+init_p(p,t)
+name_pointer p;
+@z
+
+@x
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+@y
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+#include <string.h> /* definition of |strncmp| and |strncpy| */
+@z
diff --git a/Build/source/texk/web2c/cwebdir/cweave.rc b/Build/source/texk/web2c/cwebdir/cweave.rc
new file mode 100644
index 00000000000..ac85c26e02c
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweave.rc
@@ -0,0 +1,34 @@
+/* cweave.rc: cweave resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " cweave 3.63"
+
+#define VER_INTERNALNAME_STR "cweave"
+#define VER_ORIGINALFILENAME_STR "cweave.exe"
+
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth"
+
+#define VER_FILEDESCRIPTION_STR "CWeave"
+
+#include <texlive.version>
+
+/* cweave.rc ends here */
diff --git a/Build/source/texk/web2c/cwebdir/cweave.w b/Build/source/texk/web2c/cwebdir/cweave.w
new file mode 100644
index 00000000000..91b8785bfe9
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweave.w
@@ -0,0 +1,4651 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.64 --- February 2002
+% (essentially the same as version 3.6, which added
+% recently introduced features of standard C++ to version 3.4)
+
+% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
+
+% Permission is granted to make and distribute verbatim copies of this
+% document provided that the copyright notice and this permission notice
+% are preserved on all copies.
+
+% Permission is granted to copy and distribute modified versions of this
+% document under the conditions for verbatim copying, provided that the
+% entire resulting derived work is given a different name and distributed
+% under the terms of a permission notice identical to this one.
+
+% Here is TeX material that gets inserted after \input cwebmac
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\char'174} % vertical (|) in typewriter font
+\def\dleft{[\![} \def\dright{]\!]} % double brackets
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+\def\({} % ) kludge for alphabetizing certain section names
+\def\TeXxstring{\\{\TEX/\_string}}
+\def\skipxTeX{\\{skip\_\TEX/}}
+\def\copyxTeX{\\{copy\_\TEX/}}
+
+\def\title{CWEAVE (Version 3.64)}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
+ \vskip 15pt
+ \centerline{(Version 3.64)}
+ \vfill}
+\def\botofcontents{\vfill
+\noindent
+Copyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+document provided that the copyright notice and this permission notice
+are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of this
+document under the conditions for verbatim copying, provided that the
+entire resulting derived work is given a different name and distributed
+under the terms of a permission notice identical to this one.
+}
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+@s not_eq normal @q unreserve a C++ keyword @>
+
+@** Introduction.
+This is the \.{CWEAVE} program by Silvio Levy and Donald E. Knuth,
+based on \.{WEAVE} by Knuth.
+We are thankful to Steve Avery,
+Nelson Beebe, Hans-Hermann Bode (to whom the original \CPLUSPLUS/ adaptation
+is due), Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
+Joachim Schrod, Lee Wittenberg, Saroj Mahapatra, Cesar Augusto Rorato
+Crusius, and others who have contributed improvements.
+
+The ``banner line'' defined here should be changed whenever \.{CWEAVE}
+is modified.
+
+@d banner "This is CWEAVE (Version 3.64)\n"
+
+@c @<Include files@>@/
+@h
+@<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/
+@<Typedef declarations@>@/
+@<Global variables@>@/
+@<Predeclaration of procedures@>
+
+@ We predeclare several standard system functions here instead of including
+their system header files, because the names of the header files are not as
+standard as the names of the functions. (For example, some \CEE/ environments
+have \.{<string.h>} where others have \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+extern int strcmp(); /* compare strings lexicographically */
+extern char* strcpy(); /* copy one string to another */
+extern int strncmp(); /* compare up to $n$ string characters */
+extern char* strncpy(); /* copy up to $n$ string characters */
+
+@ \.{CWEAVE} has a fairly straightforward outline. It operates in
+three phases: First it inputs the source file and stores cross-reference
+data, then it inputs the source once again and produces the \TEX/ output
+file, finally it sorts and outputs the index.
+
+Please read the documentation for \.{common}, the set of routines common
+to \.{CTANGLE} and \.{CWEAVE}, before proceeding further.
+
+@c
+int main (ac, av)
+int ac; /* argument count */
+char **av; /* argument values */
+{
+ argc=ac; argv=av;
+ program=cweave;
+ make_xrefs=force_lines=make_pb=1; /* controlled by command-line options */
+ common_init();
+ @<Set initial values@>;
+ if (show_banner) printf(banner); /* print a ``banner line'' */
+ @<Store all the reserved words@>;
+ phase_one(); /* read all the user's text and store the cross-references */
+ phase_two(); /* read all the text again and translate it to \TEX/ form */
+ phase_three(); /* output the cross-reference index */
+ return wrap_up(); /* and exit gracefully */
+}
+
+@ The following parameters were sufficient in the original \.{WEAVE} to
+handle \TEX/, so they should be sufficient for most applications of \.{CWEAVE}.
+If you change |max_bytes|, |max_names|, |hash_size|, or |buf_size|
+you have to change them also in the file |"common.w"|.
+
+@d max_bytes 90000 /* the number of bytes in identifiers,
+ index entries, and section names */
+@d max_names 4000 /* number of identifiers, strings, section names;
+ must be less than 10240; used in |"common.w"| */
+@d max_sections 2000 /* greater than the total number of sections */
+@d hash_size 353 /* should be prime */
+@d buf_size 100 /* maximum length of input line, plus one */
+@d longest_name 10000 /* section names and strings shouldn't be longer than this */
+@d long_buf_size (buf_size+longest_name)
+@d line_length 80 /* lines of \TEX/ output have at most this many characters;
+ should be less than 256 */
+@d max_refs 20000 /* number of cross-references; must be less than 65536 */
+@d max_toks 20000 /* number of symbols in \CEE/ texts being parsed;
+ must be less than 65536 */
+@d max_texts 4000 /* number of phrases in \CEE/ texts being parsed;
+ must be less than 10240 */
+@d max_scraps 2000 /* number of tokens in \CEE/ texts being parsed */
+@d stack_size 400 /* number of simultaneous output levels */
+
+@ The next few sections contain stuff from the file |"common.w"| that must
+be included in both |"ctangle.w"| and |"cweave.w"|. It appears in
+file |"common.h"|, which needs to be updated when |"common.w"| changes.
+
+@i common.h
+
+@* Data structures exclusive to {\tt CWEAVE}.
+As explained in \.{common.w}, the field of a |name_info| structure
+that contains the |rlink| of a section name is used for a completely
+different purpose in the case of identifiers. It is then called the
+|ilk| of the identifier, and it is used to
+distinguish between various types of identifiers, as follows:
+
+\yskip\hang |normal| and |func_template| identifiers are part of the
+\CEE/ program that will appear in italic type (or in typewriter type
+if all uppercase).
+
+\yskip\hang |custom| identifiers are part of the \CEE/ program that
+will be typeset in special ways.
+
+\yskip\hang |roman| identifiers are index entries that appear after
+\.{@@\^} in the \.{CWEB} file.
+
+\yskip\hang |wildcard| identifiers are index entries that appear after
+\.{@@:} in the \.{CWEB} file.
+
+\yskip\hang |typewriter| identifiers are index entries that appear after
+\.{@@.} in the \.{CWEB} file.
+
+\yskip\hang |alfop|, \dots, |template_like|
+identifiers are \CEE/ or \CPLUSPLUS/ reserved words whose |ilk|
+explains how they are to be treated when \CEE/ code is being
+formatted.
+
+@d ilk dummy.Ilk
+@d normal 0 /* ordinary identifiers have |normal| ilk */
+@d roman 1 /* normal index entries have |roman| ilk */
+@d wildcard 2 /* user-formatted index entries have |wildcard| ilk */
+@d typewriter 3 /* `typewriter type' entries have |typewriter| ilk */
+@d abnormal(a) (a->ilk>typewriter) /* tells if a name is special */
+@d func_template 4 /* identifiers that can be followed by optional template */
+@d custom 5 /* identifiers with user-given control sequence */
+@d alfop 22 /* alphabetic operators like \&{and} or \&{not\_eq} */
+@d else_like 26 /* \&{else} */
+@d public_like 40 /* \&{public}, \&{private}, \&{protected} */
+@d operator_like 41 /* \&{operator} */
+@d new_like 42 /* \&{new} */
+@d catch_like 43 /* \&{catch} */
+@d for_like 45 /* \&{for}, \&{switch}, \&{while} */
+@d do_like 46 /* \&{do} */
+@d if_like 47 /* \&{if}, \&{ifdef}, \&{endif}, \&{pragma}, \dots */
+@d delete_like 48 /* \&{delete} */
+@d raw_ubin 49 /* `\.\&' or `\.*' when looking for \&{const} following */
+@d const_like 50 /* \&{const}, \&{volatile} */
+@d raw_int 51 /* \&{int}, \&{char}, \dots; also structure and class names */
+@d int_like 52 /* same, when not followed by left parenthesis or \DC\ */
+@d case_like 53 /* \&{case}, \&{return}, \&{goto}, \&{break}, \&{continue} */
+@d sizeof_like 54 /* \&{sizeof} */
+@d struct_like 55 /* \&{struct}, \&{union}, \&{enum}, \&{class} */
+@d typedef_like 56 /* \&{typedef} */
+@d define_like 57 /* \&{define} */
+@d template_like 58 /* \&{template} */
+
+@ We keep track of the current section number in |section_count|, which
+is the total number of sections that have started. Sections which have
+been altered by a change file entry have their |changed_section| flag
+turned on during the first phase.
+
+@<Global...@>=
+boolean change_exists; /* has any section changed? */
+
+@ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
+All uses of the name |p| are recorded in a linked list beginning at
+|p->xref|, which points into the |xmem| array. The elements of |xmem|
+are structures consisting of an integer, |num|, and a pointer |xlink|
+to another element of |xmem|. If |x=p->xref| is a pointer into |xmem|,
+the value of |x->num| is either a section number where |p| is used,
+or |cite_flag| plus a section number where |p| is mentioned,
+or |def_flag| plus a section number where |p| is defined;
+and |x->xlink| points to the next such cross-reference for |p|,
+if any. This list of cross-references is in decreasing order by
+section number. The next unused slot in |xmem| is |xref_ptr|.
+The linked list ends at |&xmem[0]|.
+
+The global variable |xref_switch| is set either to |def_flag| or to zero,
+depending on whether the next cross-reference to an identifier is to be
+underlined or not in the index. This switch is set to |def_flag| when
+\.{@@!} or \.{@@d} is scanned, and it is cleared to zero when
+the next identifier or index entry cross-reference has been made.
+Similarly, the global variable |section_xref_switch| is either
+|def_flag| or |cite_flag| or zero, depending
+on whether a section name is being defined, cited or used in \CEE/ text.
+
+@<Type...@>=
+typedef struct xref_info {
+ sixteen_bits num; /* section number plus zero or |def_flag| */
+ struct xref_info *xlink; /* pointer to the previous cross-reference */
+} xref_info;
+typedef xref_info *xref_pointer;
+
+@ @<Global...@>=
+xref_info xmem[max_refs]; /* contains cross-reference information */
+xref_pointer xmem_end = xmem+max_refs-1;
+xref_pointer xref_ptr; /* the largest occupied position in |xmem| */
+sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
+
+@ A section that is used for multi-file output (with the \.{@@(} feature)
+has a special first cross-reference whose |num| field is |file_flag|.
+
+@d file_flag (3*cite_flag)
+@d def_flag (2*cite_flag)
+@d cite_flag 10240 /* must be strictly larger than |max_sections| */
+@d xref equiv_or_xref
+
+@<Set init...@>=
+xref_ptr=xmem; name_dir->xref=(char*)xmem; xref_switch=0; section_xref_switch=0;
+xmem->num=0; /* sentinel value */
+
+@ A new cross-reference for an identifier is formed by calling |new_xref|,
+which discards duplicate entries and ignores non-underlined references
+to one-letter identifiers or \CEE/'s reserved words.
+
+If the user has sent the |no_xref| flag (the \.{-x} option of the command line),
+it is unnecessary to keep track of cross-references for identifiers.
+If one were careful, one could probably make more changes around section
+100 to avoid a lot of identifier looking up.
+
+@d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference");
+ else (++xref_ptr)->num=c;
+@d no_xref (flags['x']==0)
+@d make_xrefs flags['x'] /* should cross references be output? */
+@d is_tiny(p) ((p+1)->byte_start==(p)->byte_start+1)
+@d unindexed(a) (a<res_wd_end && a->ilk>=custom)
+ /* tells if uses of a name are to be indexed */
+
+@c
+void
+new_xref(p)
+name_pointer p;
+{
+ xref_pointer q; /* pointer to previous cross-reference */
+ sixteen_bits m, n; /* new and previous cross-reference value */
+ if (no_xref) return;
+ if ((unindexed(p) || is_tiny(p)) && xref_switch==0) return;
+ m=section_count+xref_switch; xref_switch=0; q=(xref_pointer)p->xref;
+ if (q != xmem) {
+ n=q->num;
+ if (n==m || n==m+def_flag) return;
+ else if (m==n+def_flag) {
+ q->num=m; return;
+ }
+ }
+ append_xref(m); xref_ptr->xlink=q; p->xref=(char*)xref_ptr;
+}
+
+@ The cross-reference lists for section names are slightly different.
+Suppose that a section name is defined in sections $m_1$, \dots,
+$m_k$, cited in sections $n_1$, \dots, $n_l$, and used in sections
+$p_1$, \dots, $p_j$. Then its list will contain $m_1+|def_flag|$,
+\dots, $m_k+|def_flag|$, $n_1+|cite_flag|$, \dots,
+$n_l+|cite_flag|$, $p_1$, \dots, $p_j$, in this order.
+
+Although this method of storage takes quadratic time with respect to
+the length of the list, under foreseeable uses of \.{CWEAVE} this inefficiency
+is insignificant.
+
+@c
+void
+new_section_xref(p)
+name_pointer p;
+{
+ xref_pointer q,r; /* pointers to previous cross-references */
+ q=(xref_pointer)p->xref; r=xmem;
+ if (q>xmem)
+ while (q->num>section_xref_switch) {r=q; q=q->xlink;}
+ if (r->num==section_count+section_xref_switch)
+ return; /* don't duplicate entries */
+ append_xref(section_count+section_xref_switch);
+ xref_ptr->xlink=q; section_xref_switch=0;
+ if (r==xmem) p->xref=(char*)xref_ptr;
+ else r->xlink=xref_ptr;
+}
+
+@ The cross-reference list for a section name may also begin with
+|file_flag|. Here's how that flag gets put~in.
+
+@c
+void
+set_file_flag(p)
+name_pointer p;
+{
+ xref_pointer q;
+ q=(xref_pointer)p->xref;
+ if (q->num==file_flag) return;
+ append_xref(file_flag);
+ xref_ptr->xlink = q;
+ p->xref = (char *)xref_ptr;
+}
+
+@ A third large area of memory is used for sixteen-bit `tokens', which appear
+in short lists similar to the strings of characters in |byte_mem|. Token lists
+are used to contain the result of \CEE/ code translated into \TEX/ form;
+further details about them will be explained later. A |text_pointer| variable
+is an index into |tok_start|.
+
+@<Typed...@>=
+typedef sixteen_bits token;
+typedef token *token_pointer;
+typedef token_pointer *text_pointer;
+
+@ The first position of |tok_mem|
+that is unoccupied by replacement text is called |tok_ptr|, and the first
+unused location of |tok_start| is called |text_ptr|.
+Thus, we usually have |*text_ptr==tok_ptr|.
+
+@<Global...@>=
+token tok_mem[max_toks]; /* tokens */
+token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */
+token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
+token_pointer tok_ptr; /* first unused position in |tok_mem| */
+text_pointer text_ptr; /* first unused position in |tok_start| */
+text_pointer tok_start_end = tok_start+max_texts-1; /* end of |tok_start| */
+token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
+text_pointer max_text_ptr; /* largest value of |text_ptr| */
+
+@ @<Set init...@>=
+tok_ptr=tok_mem+1; text_ptr=tok_start+1; tok_start[0]=tok_mem+1;
+tok_start[1]=tok_mem+1;
+max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
+
+@ Here are the three procedures needed to complete |id_lookup|:
+@c
+int names_match(p,first,l,t)
+name_pointer p; /* points to the proposed match */
+char *first; /* position of first character of string */
+int l; /* length of identifier */
+eight_bits t; /* desired ilk */
+{
+ if (length(p)!=l) return 0;
+ if (p->ilk!=t && !(t==normal && abnormal(p))) return 0;
+ return !strncmp(first,p->byte_start,l);
+}
+
+void
+init_p(p,t)
+name_pointer p;
+eight_bits t;
+{
+ p->ilk=t; p->xref=(char*)xmem;
+}
+
+void
+init_node(p)
+name_pointer p;
+{
+ p->xref=(char*)xmem;
+}
+
+@ We have to get \CEE/'s
+reserved words into the hash table, and the simplest way to do this is
+to insert them every time \.{CWEAVE} is run. Fortunately there are relatively
+few reserved words. (Some of these are not strictly ``reserved,'' but
+are defined in header files of the ISO Standard \CEE/ Library.)
+@^reserved words@>
+
+@<Store all the reserved words@>=
+id_lookup("and",NULL,alfop);
+id_lookup("and_eq",NULL,alfop);
+id_lookup("asm",NULL,sizeof_like);
+id_lookup("auto",NULL,int_like);
+id_lookup("bitand",NULL,alfop);
+id_lookup("bitor",NULL,alfop);
+id_lookup("bool",NULL,raw_int);
+id_lookup("break",NULL,case_like);
+id_lookup("case",NULL,case_like);
+id_lookup("catch",NULL,catch_like);
+id_lookup("char",NULL,raw_int);
+id_lookup("class",NULL,struct_like);
+id_lookup("clock_t",NULL,raw_int);
+id_lookup("compl",NULL,alfop);
+id_lookup("const",NULL,const_like);
+id_lookup("const_cast",NULL,raw_int);
+id_lookup("continue",NULL,case_like);
+id_lookup("default",NULL,case_like);
+id_lookup("define",NULL,define_like);
+id_lookup("defined",NULL,sizeof_like);
+id_lookup("delete",NULL,delete_like);
+id_lookup("div_t",NULL,raw_int);
+id_lookup("do",NULL,do_like);
+id_lookup("double",NULL,raw_int);
+id_lookup("dynamic_cast",NULL,raw_int);
+id_lookup("elif",NULL,if_like);
+id_lookup("else",NULL,else_like);
+id_lookup("endif",NULL,if_like);
+id_lookup("enum",NULL,struct_like);
+id_lookup("error",NULL,if_like);
+id_lookup("explicit",NULL,int_like);
+id_lookup("export",NULL,int_like);
+id_lookup("extern",NULL,int_like);
+id_lookup("FILE",NULL,raw_int);
+id_lookup("float",NULL,raw_int);
+id_lookup("for",NULL,for_like);
+id_lookup("fpos_t",NULL,raw_int);
+id_lookup("friend",NULL,int_like);
+id_lookup("goto",NULL,case_like);
+id_lookup("if",NULL,if_like);
+id_lookup("ifdef",NULL,if_like);
+id_lookup("ifndef",NULL,if_like);
+id_lookup("include",NULL,if_like);
+id_lookup("inline",NULL,int_like);
+id_lookup("int",NULL,raw_int);
+id_lookup("jmp_buf",NULL,raw_int);
+id_lookup("ldiv_t",NULL,raw_int);
+id_lookup("line",NULL,if_like);
+id_lookup("long",NULL,raw_int);
+id_lookup("mutable",NULL,int_like);
+id_lookup("namespace",NULL,struct_like);
+id_lookup("new",NULL,new_like);
+id_lookup("not",NULL,alfop);
+id_lookup("not_eq",NULL,alfop);
+id_lookup("NULL",NULL,custom);
+id_lookup("offsetof",NULL,raw_int);
+id_lookup("operator",NULL,operator_like);
+id_lookup("or",NULL,alfop);
+id_lookup("or_eq",NULL,alfop);
+id_lookup("pragma",NULL,if_like);
+id_lookup("private",NULL,public_like);
+id_lookup("protected",NULL,public_like);
+id_lookup("ptrdiff_t",NULL,raw_int);
+id_lookup("public",NULL,public_like);
+id_lookup("register",NULL,int_like);
+id_lookup("reinterpret_cast",NULL,raw_int);
+id_lookup("return",NULL,case_like);
+id_lookup("short",NULL,raw_int);
+id_lookup("sig_atomic_t",NULL,raw_int);
+id_lookup("signed",NULL,raw_int);
+id_lookup("size_t",NULL,raw_int);
+id_lookup("sizeof",NULL,sizeof_like);
+id_lookup("static",NULL,int_like);
+id_lookup("static_cast",NULL,raw_int);
+id_lookup("struct",NULL,struct_like);
+id_lookup("switch",NULL,for_like);
+id_lookup("template",NULL,template_like);
+id_lookup("this",NULL,custom);
+id_lookup("throw",NULL,case_like);
+id_lookup("time_t",NULL,raw_int);
+id_lookup("try",NULL,else_like);
+id_lookup("typedef",NULL,typedef_like);
+id_lookup("typeid",NULL,raw_int);
+id_lookup("typename",NULL,struct_like);
+id_lookup("undef",NULL,if_like);
+id_lookup("union",NULL,struct_like);
+id_lookup("unsigned",NULL,raw_int);
+id_lookup("using",NULL,int_like);
+id_lookup("va_dcl",NULL,decl); /* Berkeley's variable-arg-list convention */
+id_lookup("va_list",NULL,raw_int); /* ditto */
+id_lookup("virtual",NULL,int_like);
+id_lookup("void",NULL,raw_int);
+id_lookup("volatile",NULL,const_like);
+id_lookup("wchar_t",NULL,raw_int);
+id_lookup("while",NULL,for_like);
+id_lookup("xor",NULL,alfop);
+id_lookup("xor_eq",NULL,alfop);
+res_wd_end=name_ptr;
+id_lookup("TeX",NULL,custom);
+id_lookup("make_pair",NULL,func_template);
+
+@* Lexical scanning.
+Let us now consider the subroutines that read the \.{CWEB} source file
+and break it into meaningful units. There are four such procedures:
+One simply skips to the next `\.{@@\ }' or `\.{@@*}' that begins a
+section; another passes over the \TEX/ text at the beginning of a
+section; the third passes over the \TEX/ text in a \CEE/ comment;
+and the last, which is the most interesting, gets the next token of
+a \CEE/ text. They all use the pointers |limit| and |loc| into
+the line of input currently being studied.
+
+@ Control codes in \.{CWEB}, which begin with `\.{@@}', are converted
+into a numeric code designed to simplify \.{CWEAVE}'s logic; for example,
+larger numbers are given to the control codes that denote more significant
+milestones, and the code of |new_section| should be the largest of
+all. Some of these numeric control codes take the place of |char|
+control codes that will not otherwise appear in the output of the
+scanning routines.
+@^ASCII code dependencies@>
+
+@d ignore 00 /* control code of no interest to \.{CWEAVE} */
+@d verbatim 02 /* takes the place of extended ASCII \.{\char2} */
+@d begin_short_comment 03 /* \CPLUSPLUS/ short comment */
+@d begin_comment '\t' /* tab marks will not appear */
+@d underline '\n' /* this code will be intercepted without confusion */
+@d noop 0177 /* takes the place of ASCII delete */
+@d xref_roman 0203 /* control code for `\.{@@\^}' */
+@d xref_wildcard 0204 /* control code for `\.{@@:}' */
+@d xref_typewriter 0205 /* control code for `\.{@@.}' */
+@d TeX_string 0206 /* control code for `\.{@@t}' */
+@f TeX_string TeX
+@d ord 0207 /* control code for `\.{@@'}' */
+@d join 0210 /* control code for `\.{@@\&}' */
+@d thin_space 0211 /* control code for `\.{@@,}' */
+@d math_break 0212 /* control code for `\.{@@\v}' */
+@d line_break 0213 /* control code for `\.{@@/}' */
+@d big_line_break 0214 /* control code for `\.{@@\#}' */
+@d no_line_break 0215 /* control code for `\.{@@+}' */
+@d pseudo_semi 0216 /* control code for `\.{@@;}' */
+@d macro_arg_open 0220 /* control code for `\.{@@[}' */
+@d macro_arg_close 0221 /* control code for `\.{@@]}' */
+@d trace 0222 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
+@d translit_code 0223 /* control code for `\.{@@l}' */
+@d output_defs_code 0224 /* control code for `\.{@@h}' */
+@d format_code 0225 /* control code for `\.{@@f}' and `\.{@@s}' */
+@d definition 0226 /* control code for `\.{@@d}' */
+@d begin_C 0227 /* control code for `\.{@@c}' */
+@d section_name 0230 /* control code for `\.{@@<}' */
+@d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
+
+@ Control codes are converted to \.{CWEAVE}'s internal
+representation by means of the table |ccode|.
+
+@<Global...@>=
+eight_bits ccode[256]; /* meaning of a char following \.{@@} */
+
+@ @<Set ini...@>=
+{int c; for (c=0; c<256; c++) ccode[c]=0;}
+ccode[' ']=ccode['\t']=ccode['\n']=ccode['\v']=ccode['\r']=ccode['\f']
+ =ccode['*']=new_section;
+ccode['@@']='@@'; /* `quoted' at sign */
+ccode['=']=verbatim;
+ccode['d']=ccode['D']=definition;
+ccode['f']=ccode['F']=ccode['s']=ccode['S']=format_code;
+ccode['c']=ccode['C']=ccode['p']=ccode['P']=begin_C;
+ccode['t']=ccode['T']=TeX_string;
+ccode['l']=ccode['L']=translit_code;
+ccode['q']=ccode['Q']=noop;
+ccode['h']=ccode['H']=output_defs_code;
+ccode['&']=join; ccode['<']=ccode['(']=section_name;
+ccode['!']=underline; ccode['^']=xref_roman;
+ccode[':']=xref_wildcard; ccode['.']=xref_typewriter; ccode[',']=thin_space;
+ccode['|']=math_break; ccode['/']=line_break; ccode['#']=big_line_break;
+ccode['+']=no_line_break; ccode[';']=pseudo_semi;
+ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
+ccode['\'']=ord;
+@<Special control codes for debugging@>@;
+
+@ Users can write
+\.{@@2}, \.{@@1}, and \.{@@0} to turn tracing fully on, partly on,
+and off, respectively.
+
+@<Special control codes...@>=
+ccode['0']=ccode['1']=ccode['2']=trace;
+
+@ The |skip_limbo| routine is used on the first pass to skip through
+portions of the input that are not in any sections, i.e., that precede
+the first section. After this procedure has been called, the value of
+|input_has_ended| will tell whether or not a section has actually been found.
+
+There's a complication that we will postpone until later: If the \.{@@s}
+operation appears in limbo, we want to use it to adjust the default
+interpretation of identifiers.
+
+@<Predec...@>=
+void skip_limbo();
+
+@ @c
+void
+skip_limbo() {
+ while(1) {
+ if (loc>limit && get_line()==0) return;
+ *(limit+1)='@@';
+ while (*loc!='@@') loc++; /* look for '@@', then skip two chars */
+ if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++];
+ if (c==new_section) return;
+ if (c==noop) skip_restricted();
+ else if (c==format_code) @<Process simple format in limbo@>;
+ }
+ }
+}
+
+@ The |skip_TeX| routine is used on the first pass to skip through
+the \TEX/ code at the beginning of a section. It returns the next
+control code or `\.{\v}' found in the input. A |new_section| is
+assumed to exist at the very end of the file.
+
+@f skip_TeX TeX
+
+@c
+unsigned
+skip_TeX() /* skip past pure \TEX/ code */
+{
+ while (1) {
+ if (loc>limit && get_line()==0) return(new_section);
+ *(limit+1)='@@';
+ while (*loc!='@@' && *loc!='|') loc++;
+ if (*loc++ =='|') return('|');
+ if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
+ }
+}
+
+@*1 Inputting the next token.
+As stated above, \.{CWEAVE}'s most interesting lexical scanning routine is the
+|get_next| function that inputs the next token of \CEE/ input. However,
+|get_next| is not especially complicated.
+
+The result of |get_next| is either a |char| code for some special character,
+or it is a special code representing a pair of characters (e.g., `\.{!=}'),
+or it is the numeric value computed by the |ccode|
+table, or it is one of the following special codes:
+
+\yskip\hang |identifier|: In this case the global variables |id_first| and
+|id_loc| will have been set to the beginning and ending-plus-one locations
+in the buffer, as required by the |id_lookup| routine.
+
+\yskip\hang |string|: The string will have been copied into the array
+|section_text|; |id_first| and |id_loc| are set as above (now they are
+pointers into |section_text|).
+
+\yskip\hang |constant|: The constant is copied into |section_text|, with
+slight modifications; |id_first| and |id_loc| are set.
+
+\yskip\noindent Furthermore, some of the control codes cause
+|get_next| to take additional actions:
+
+\yskip\hang |xref_roman|, |xref_wildcard|, |xref_typewriter|, |TeX_string|,
+|verbatim|: The values of |id_first| and |id_loc| will have been set to
+the beginning and ending-plus-one locations in the buffer.
+
+\yskip\hang |section_name|: In this case the global variable |cur_section| will
+point to the |byte_start| entry for the section name that has just been scanned.
+The value of |cur_section_char| will be |'('| if the section name was
+preceded by \.{@@(} instead of \.{@@<}.
+
+\yskip\noindent If |get_next| sees `\.{@@!}'
+it sets |xref_switch| to |def_flag| and goes on to the next token.
+
+@d constant 0200 /* \CEE/ constant */
+@d string 0201 /* \CEE/ string */
+@d identifier 0202 /* \CEE/ identifier or reserved word */
+
+@<Global...@>=
+name_pointer cur_section; /* name of section just scanned */
+char cur_section_char; /* the character just before that name */
+
+@ @<Include...@>=
+#include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
+#include <stdlib.h> /* definition of |exit| */
+
+@ As one might expect, |get_next| consists mostly of a big switch
+that branches to the various special cases that can arise.
+\CEE/ allows underscores to appear in identifiers, and some \CEE/
+compilers even allow the dollar sign.
+
+@d isxalpha(c) ((c)=='_' || (c)=='$')
+ /* non-alpha characters allowed in identifier */
+@d ishigh(c) ((eight_bits)(c)>0177)
+@^high-bit character handling@>
+
+@<Predecl...@>=
+eight_bits get_next();
+
+@ @c
+eight_bits
+get_next() /* produces the next input token */
+{@+eight_bits c; /* the current character */
+ while (1) {
+ @<Check if we're at the end of a preprocessor command@>;
+ if (loc>limit && get_line()==0) return(new_section);
+ c=*(loc++);
+ if (xisdigit(c) || c=='.') @<Get a constant@>@;
+ else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"'))@|
+ || (c=='<' && sharp_include_line==1))
+ @<Get a string@>@;
+ else if (xisalpha(c) || isxalpha(c) || ishigh(c))
+ @<Get an identifier@>@;
+ else if (c=='@@') @<Get control code and possible section name@>@;
+ else if (xisspace(c)) continue; /* ignore spaces and tabs */
+ if (c=='#' && loc==buffer+1) @<Raise preprocessor flag@>;
+ mistake: @<Compress two-symbol operator@>@;
+ return(c);
+ }
+}
+
+@ Because preprocessor commands do not fit in with the rest of the syntax
+of \CEE/,
+we have to deal with them separately. One solution is to enclose such
+commands between special markers. Thus, when a \.\# is seen as the
+first character of a line, |get_next| returns a special code
+|left_preproc| and raises a flag |preprocessing|.
+
+We can use the same internal code number for |left_preproc| as we do
+for |ord|, since |get_next| changes |ord| into a string.
+
+@d left_preproc ord /* begins a preprocessor command */
+@d right_preproc 0217 /* ends a preprocessor command */
+
+@<Glob...@>=
+boolean preprocessing=0; /* are we scanning a preprocessor command? */
+
+@ @<Raise prep...@>= {
+ preprocessing=1;
+ @<Check if next token is |include|@>;
+ return (left_preproc);
+}
+
+@ An additional complication is the freakish use of \.< and \.> to delimit
+a file name in lines that start with \.{\#include}. We must treat this file
+name as a string.
+
+@<Glob...@>=
+boolean sharp_include_line=0; /* are we scanning a |#include| line? */
+
+@ @<Check if next token is |include|@>=
+while (loc<=buffer_end-7 && xisspace(*loc)) loc++;
+if (loc<=buffer_end-6 && strncmp(loc,"include",7)==0) sharp_include_line=1;
+
+@ When we get to the end of a preprocessor line,
+we lower the flag and send a code |right_preproc|, unless
+the last character was a \.\\.
+
+@<Check if we're at...@>=
+ while (loc==limit-1 && preprocessing && *loc=='\\')
+ if (get_line()==0) return(new_section); /* still in preprocessor mode */
+ if (loc>=limit && preprocessing) {
+ preprocessing=sharp_include_line=0;
+ return(right_preproc);
+ }
+
+@ The following code assigns values to the combinations \.{++},
+\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{\v\v}, and
+\.{\&\&}, and to the \CPLUSPLUS/
+combinations \.{...}, \.{::}, \.{.*} and \.{->*}.
+The compound assignment operators (e.g., \.{+=}) are
+treated as separate tokens.
+
+@d compress(c) if (loc++<=limit) return(c)
+
+@<Compress tw...@>=
+switch(c) {
+ case '/': if (*loc=='*') {compress(begin_comment);}
+ else if (*loc=='/') compress(begin_short_comment); break;
+ case '+': if (*loc=='+') compress(plus_plus); break;
+ case '-': if (*loc=='-') {compress(minus_minus);}
+ else if (*loc=='>') if (*(loc+1)=='*') {loc++; compress(minus_gt_ast);}
+ else compress(minus_gt); break;
+ case '.': if (*loc=='*') {compress(period_ast);}
+ else if (*loc=='.' && *(loc+1)=='.') {
+ loc++; compress(dot_dot_dot);
+ }
+ break;
+ case ':': if (*loc==':') compress(colon_colon); break;
+ case '=': if (*loc=='=') compress(eq_eq); break;
+ case '>': if (*loc=='=') {compress(gt_eq);}
+ else if (*loc=='>') compress(gt_gt); break;
+ case '<': if (*loc=='=') {compress(lt_eq);}
+ else if (*loc=='<') compress(lt_lt); break;
+ case '&': if (*loc=='&') compress(and_and); break;
+ case '|': if (*loc=='|') compress(or_or); break;
+ case '!': if (*loc=='=') compress(not_eq); break;
+}
+
+@ @<Get an identifier@>= {
+ id_first=--loc;
+ while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
+ id_loc=loc; return(identifier);
+}
+
+@ Different conventions are followed by \TEX/ and \CEE/ to express octal
+and hexadecimal numbers; it is reasonable to stick to each convention
+within its realm. Thus the \CEE/ part of a \.{CWEB} file has octals
+introduced by \.0 and hexadecimals by \.{0x}, but \.{CWEAVE} will print
+with \TEX/ macros that the user can redefine to fit the context.
+In order to simplify such macros, we replace some of the characters.
+
+Notice that in this section and the next, |id_first| and |id_loc|
+are pointers into the array |section_text|, not into |buffer|.
+
+@<Get a constant@>= {
+ id_first=id_loc=section_text+1;
+ if (*(loc-1)=='0') {
+ if (*loc=='x' || *loc=='X') {*id_loc++='^'; loc++;
+ while (xisxdigit(*loc)) *id_loc++=*loc++;} /* hex constant */
+ else if (xisdigit(*loc)) {*id_loc++='~';
+ while (xisdigit(*loc)) *id_loc++=*loc++;} /* octal constant */
+ else goto dec; /* decimal constant */
+ }
+ else { /* decimal constant */
+ if (*(loc-1)=='.' && !xisdigit(*loc)) goto mistake; /* not a constant */
+ dec: *id_loc++=*(loc-1);
+ while (xisdigit(*loc) || *loc=='.') *id_loc++=*loc++;
+ if (*loc=='e' || *loc=='E') { /* float constant */
+ *id_loc++='_'; loc++;
+ if (*loc=='+' || *loc=='-') *id_loc++=*loc++;
+ while (xisdigit(*loc)) *id_loc++=*loc++;
+ }
+ }
+ while (*loc=='u' || *loc=='U' || *loc=='l' || *loc=='L'
+ || *loc=='f' || *loc=='F') {
+ *id_loc++='$'; *id_loc++=toupper(*loc); loc++;
+ }
+ return(constant);
+}
+
+@ \CEE/ strings and character constants, delimited by double and single
+quotes, respectively, can contain newlines or instances of their own
+delimiters if they are protected by a backslash. We follow this
+convention, but do not allow the string to be longer than |longest_name|.
+
+@<Get a string@>= {
+ char delim = c; /* what started the string */
+ id_first = section_text+1;
+ id_loc = section_text;
+ if (delim=='\'' && *(loc-2)=='@@') {*++id_loc='@@'; *++id_loc='@@';}
+ *++id_loc=delim;
+ if (delim=='L') { /* wide character constant */
+ delim=*loc++; *++id_loc=delim;
+ }
+ if (delim=='<') delim='>'; /* for file names in |#include| lines */
+ while (1) {
+ if (loc>=limit) {
+ if(*(limit-1)!='\\') {
+ err_print("! String didn't end"); loc=limit; break;
+@.String didn't end@>
+ }
+ if(get_line()==0) {
+ err_print("! Input ended in middle of string"); loc=buffer; break;
+@.Input ended in middle of string@>
+ }
+ }
+ if ((c=*loc++)==delim) {
+ if (++id_loc<=section_text_end) *id_loc=c;
+ break;
+ }
+ if (c=='\\') if (loc>=limit) continue;
+ else if (++id_loc<=section_text_end) {
+ *id_loc = '\\'; c=*loc++;
+ }
+ if (++id_loc<=section_text_end) *id_loc=c;
+ }
+ if (id_loc>=section_text_end) {
+ printf("\n! String too long: ");
+@.String too long@>
+ term_write(section_text+1,25);
+ printf("..."); mark_error;
+ }
+ id_loc++;
+ return(string);
+}
+
+@ After an \.{@@} sign has been scanned, the next character tells us
+whether there is more work to do.
+
+@<Get control code and possible section name@>= {
+ c=*loc++;
+ switch(ccode[(eight_bits)c]) {
+ case translit_code: err_print("! Use @@l in limbo only"); continue;
+@.Use @@l in limbo...@>
+ case underline: xref_switch=def_flag; continue;
+ case trace: tracing=c-'0'; continue;
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case noop: case TeX_string: c=ccode[c]; skip_restricted(); return(c);
+ case section_name:
+ @<Scan the section name and make |cur_section| point to it@>;
+ case verbatim: @<Scan a verbatim string@>;
+ case ord: @<Get a string@>;
+ default: return(ccode[(eight_bits)c]);
+ }
+}
+
+@ The occurrence of a section name sets |xref_switch| to zero,
+because the section name might (for example) follow \&{int}.
+
+@<Scan the section name...@>= {
+ char *k; /* pointer into |section_text| */
+ cur_section_char=*(loc-1);
+ @<Put section name into |section_text|@>;
+ if (k-section_text>3 && strncmp(k-2,"...",3)==0)
+ cur_section=section_lookup(section_text+1,k-3,1); /* 1 indicates a prefix */
+ else cur_section=section_lookup(section_text+1,k,0);
+ xref_switch=0; return(section_name);
+}
+
+@ Section names are placed into the |section_text| array with consecutive spaces,
+tabs, and carriage-returns replaced by single spaces. There will be no
+spaces at the beginning or the end. (We set |section_text[0]=' '| to facilitate
+this, since the |section_lookup| routine uses |section_text[1]| as the first
+character of the name.)
+
+@<Set init...@>=section_text[0]=' ';
+
+@ @<Put section name...@>=
+k=section_text;
+while (1) {
+ if (loc>limit && get_line()==0) {
+ err_print("! Input ended in section name");
+@.Input ended in section name@>
+ loc=buffer+1; break;
+ }
+ c=*loc;
+ @<If end of name or erroneous control code, |break|@>;
+ loc++; if (k<section_text_end) k++;
+ if (xisspace(c)) {
+ c=' '; if (*(k-1)==' ') k--;
+ }
+*k=c;
+}
+if (k>=section_text_end) {
+ printf("\n! Section name too long: ");
+@.Section name too long@>
+ term_write(section_text+1,25);
+ printf("..."); mark_harmless;
+}
+if (*k==' ' && k>section_text) k--;
+
+@ @<If end of name...@>=
+if (c=='@@') {
+ c=*(loc+1);
+ if (c=='>') {
+ loc+=2; break;
+ }
+ if (ccode[(eight_bits)c]==new_section) {
+ err_print("! Section name didn't end"); break;
+@.Section name didn't end@>
+ }
+ if (c!='@@') {
+ err_print("! Control codes are forbidden in section name"); break;
+@.Control codes are forbidden...@>
+ }
+ *(++k)='@@'; loc++; /* now |c==*loc| again */
+}
+
+@ This function skips over a restricted context at relatively high speed.
+
+@<Predecl...@>=
+void skip_restricted();
+
+@ @c
+void
+skip_restricted()
+{
+ id_first=loc; *(limit+1)='@@';
+false_alarm:
+ while (*loc!='@@') loc++;
+ id_loc=loc;
+ if (loc++>limit) {
+ err_print("! Control text didn't end"); loc=limit;
+@.Control text didn't end@>
+ }
+ else {
+ if (*loc=='@@'&&loc<=limit) {loc++; goto false_alarm;}
+ if (*loc++!='>')
+ err_print("! Control codes are forbidden in control text");
+@.Control codes are forbidden...@>
+ }
+}
+
+@ At the present point in the program we
+have |*(loc-1)==verbatim|; we set |id_first| to the beginning
+of the string itself, and |id_loc| to its ending-plus-one location in the
+buffer. We also set |loc| to the position just after the ending delimiter.
+
+@<Scan a verbatim string@>= {
+ id_first=loc++; *(limit+1)='@@'; *(limit+2)='>';
+ while (*loc!='@@' || *(loc+1)!='>') loc++;
+ if (loc>=limit) err_print("! Verbatim string didn't end");
+@.Verbatim string didn't end@>
+ id_loc=loc; loc+=2;
+ return (verbatim);
+}
+
+@** Phase one processing.
+We now have accumulated enough subroutines to make it possible to carry out
+\.{CWEAVE}'s first pass over the source file. If everything works right,
+both phase one and phase two of \.{CWEAVE} will assign the same numbers to
+sections, and these numbers will agree with what \.{CTANGLE} does.
+
+The global variable |next_control| often contains the most recent output of
+|get_next|; in interesting cases, this will be the control code that
+ended a section or part of a section.
+
+@<Global...@>=
+eight_bits next_control; /* control code waiting to be acting upon */
+
+@ The overall processing strategy in phase one has the following
+straightforward outline.
+
+@<Predecl...@>=
+void phase_one();
+
+@ @c
+void
+phase_one() {
+ phase=1; reset_input(); section_count=0;
+ skip_limbo(); change_exists=0;
+ while (!input_has_ended)
+ @<Store cross-reference data for the current section@>;
+ changed_section[section_count]=change_exists;
+ /* the index changes if anything does */
+ phase=2; /* prepare for second phase */
+ @<Print error messages about unused or undefined section names@>;
+}
+
+@ @<Store cross-reference data...@>=
+{
+ if (++section_count==max_sections) overflow("section number");
+ changed_section[section_count]=changing;
+ /* it will become 1 if any line changes */
+ if (*(loc-1)=='*' && show_progress) {
+ printf("*%d",section_count);
+ update_terminal; /* print a progress report */
+ }
+ @<Store cross-references in the \TEX/ part of a section@>;
+ @<Store cross-references in the definition part of a section@>;
+ @<Store cross-references in the \CEE/ part of a section@>;
+ if (changed_section[section_count]) change_exists=1;
+}
+
+@ The |C_xref| subroutine stores references to identifiers in
+\CEE/ text material beginning with the current value of |next_control|
+and continuing until |next_control| is `\.\{' or `\.{\v}', or until the next
+``milestone'' is passed (i.e., |next_control>=format_code|). If
+|next_control>=format_code| when |C_xref| is called, nothing will happen;
+but if |next_control=='|'| upon entry, the procedure assumes that this is
+the `\.{\v}' preceding \CEE/ text that is to be processed.
+
+The parameter |spec_ctrl| is used to change this behavior. In most cases
+|C_xref| is called with |spec_ctrl==ignore|, which triggers the default
+processing described above. If |spec_ctrl==section_name|, section names will
+be gobbled. This is used when \CEE/ text in the \TEX/ part or inside comments
+is parsed: It allows for section names to appear in \pb, but these
+strings will not be entered into the cross reference lists since they are not
+definitions of section names.
+
+The program uses the fact that our internal code numbers satisfy
+the relations |xref_roman==identifier+roman| and |xref_wildcard==identifier
++wildcard| and |xref_typewriter==identifier+typewriter|,
+as well as |normal==0|.
+
+@<Predecl...@>=
+void C_xref();
+
+@ @c
+void
+C_xref( spec_ctrl ) /* makes cross-references for \CEE/ identifiers */
+ eight_bits spec_ctrl;
+{
+ name_pointer p; /* a referenced name */
+ while (next_control<format_code || next_control==spec_ctrl) {
+ if (next_control>=identifier && next_control<=xref_typewriter) {
+ if (next_control>identifier) @<Replace |"@@@@"| by |"@@"| @>@;
+ p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p);
+ }
+ if (next_control==section_name) {
+ section_xref_switch=cite_flag;
+ new_section_xref(cur_section);
+ }
+ next_control=get_next();
+ if (next_control=='|' || next_control==begin_comment ||
+ next_control==begin_short_comment) return;
+ }
+}
+
+@ The |outer_xref| subroutine is like |C_xref| except that it begins
+with |next_control!='|'| and ends with |next_control>=format_code|. Thus, it
+handles \CEE/ text with embedded comments.
+
+@<Predecl...@>=
+void outer_xref();
+
+@ @c
+void
+outer_xref() /* extension of |C_xref| */
+{
+ int bal; /* brace level in comment */
+ while (next_control<format_code)
+ if (next_control!=begin_comment && next_control!=begin_short_comment)
+ C_xref(ignore);
+ else {
+ boolean is_long_comment=(next_control==begin_comment);
+ bal=copy_comment(is_long_comment,1); next_control='|';
+ while (bal>0) {
+ C_xref(section_name); /* do not reference section names in comments */
+ if (next_control=='|') bal=copy_comment(is_long_comment,bal);
+ else bal=0; /* an error message will occur in phase two */
+ }
+ }
+}
+
+@ In the \TEX/ part of a section, cross-reference entries are made only for
+the identifiers in \CEE/ texts enclosed in \pb, or for control texts
+enclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>}
+or \.{@@:}$\,\ldots\,$\.{@@>}.
+
+@<Store cross-references in the \T...@>=
+while (1) {
+ switch (next_control=skip_TeX()) {
+ case translit_code: err_print("! Use @@l in limbo only"); continue;
+@.Use @@l in limbo...@>
+ case underline: xref_switch=def_flag; continue;
+ case trace: tracing=*(loc-1)-'0'; continue;
+ case '|': C_xref(section_name); break;
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case noop: case section_name:
+ loc-=2; next_control=get_next(); /* scan to \.{@@>} */
+ if (next_control>=xref_roman && next_control<=xref_typewriter) {
+ @<Replace |"@@@@"| by |"@@"| @>@;
+ new_xref(id_lookup(id_first, id_loc,next_control-identifier));
+ }
+ break;
+ }
+ if (next_control>=format_code) break;
+}
+
+@ @<Replace |"@@@@"| by |"@@"| @>=
+{
+ char *src=id_first,*dst=id_first;
+ while(src<id_loc){
+ if(*src=='@@') src++;
+ *dst++=*src++;
+ }
+ id_loc=dst;
+ while (dst<src) *dst++=' '; /* clean up in case of error message display */
+}
+
+@ During the definition and \CEE/ parts of a section, cross-references
+are made for all identifiers except reserved words. However, the right
+identifier in a format definition is not referenced, and the left
+identifier is referenced only if it has been explicitly
+underlined (preceded by \.{@@!}).
+The \TEX/ code in comments is, of course, ignored, except for
+\CEE/ portions enclosed in \pb; the text of a section name is skipped
+entirely, even if it contains \pb\ constructions.
+
+The variables |lhs| and |rhs| point to the respective identifiers involved
+in a format definition.
+
+@<Global...@>=
+name_pointer lhs, rhs; /* pointers to |byte_start| for format identifiers */
+name_pointer res_wd_end; /* pointer to the first nonreserved identifier */
+
+@ When we get to the following code we have |next_control>=format_code|.
+
+@<Store cross-references in the d...@>=
+while (next_control<=definition) { /* |format_code| or |definition| */
+ if (next_control==definition) {
+ xref_switch=def_flag; /* implied \.{@@!} */
+ next_control=get_next();
+ } else @<Process a format definition@>;
+ outer_xref();
+}
+
+@ Error messages for improper format definitions will be issued in phase
+two. Our job in phase one is to define the |ilk| of a properly formatted
+identifier, and to remove cross-references to identifiers that we now
+discover should be unindexed.
+
+@<Process a form...@>= {
+ next_control=get_next();
+ if (next_control==identifier) {
+ lhs=id_lookup(id_first, id_loc,normal); lhs->ilk=normal;
+ if (xref_switch) new_xref(lhs);
+ next_control=get_next();
+ if (next_control==identifier) {
+ rhs=id_lookup(id_first, id_loc,normal);
+ lhs->ilk=rhs->ilk;
+ if (unindexed(lhs)) { /* retain only underlined entries */
+ xref_pointer q,r=NULL;
+ for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)
+ if (q->num<def_flag)
+ if (r) r->xlink=q->xlink;
+ else lhs->xref=(char*)q->xlink;
+ else r=q;
+ }
+ next_control=get_next();
+ }
+ }
+}
+
+@ A much simpler processing of format definitions occurs when the
+definition is found in limbo.
+
+@<Process simple format in limbo@>=
+{
+ if (get_next()!=identifier)
+ err_print("! Missing left identifier of @@s");
+@.Missing left identifier...@>
+ else {
+ lhs=id_lookup(id_first,id_loc,normal);
+ if (get_next()!=identifier)
+ err_print("! Missing right identifier of @@s");
+@.Missing right identifier...@>
+ else {
+ rhs=id_lookup(id_first,id_loc,normal);
+ lhs->ilk=rhs->ilk;
+ }
+ }
+}
+
+@ Finally, when the \TEX/ and definition parts have been treated, we have
+|next_control>=begin_C|.
+
+@<Store cross-references in the \CEE/...@>=
+if (next_control<=section_name) { /* |begin_C| or |section_name| */
+ if (next_control==begin_C) section_xref_switch=0;
+ else {
+ section_xref_switch=def_flag;
+ if(cur_section_char=='(' && cur_section!=name_dir)
+ set_file_flag(cur_section);
+ }
+ do {
+ if (next_control==section_name && cur_section!=name_dir)
+ new_section_xref(cur_section);
+ next_control=get_next(); outer_xref();
+ } while ( next_control<=section_name);
+}
+
+@ After phase one has looked at everything, we want to check that each
+section name was both defined and used. The variable |cur_xref| will point
+to cross-references for the current section name of interest.
+
+@<Global...@>=
+xref_pointer cur_xref; /* temporary cross-reference pointer */
+boolean an_output; /* did |file_flag| precede |cur_xref|? */
+
+@ The following recursive procedure
+walks through the tree of section names and prints out anomalies.
+@^recursion@>
+
+@<Predecl...@>=
+void section_check();
+
+@ @c
+void
+section_check(p)
+name_pointer p; /* print anomalies in subtree |p| */
+{
+ if (p) {
+ section_check(p->llink);
+ cur_xref=(xref_pointer)p->xref;
+ if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num <def_flag) {
+ printf("\n! Never defined: <"); print_section_name(p); putchar('>'); mark_harmless;
+@.Never defined: <section name>@>
+ }
+ while (cur_xref->num >=cite_flag) cur_xref=cur_xref->xlink;
+ if (cur_xref==xmem && !an_output) {
+ printf("\n! Never used: <"); print_section_name(p); putchar('>'); mark_harmless;
+@.Never used: <section name>@>
+ }
+ section_check(p->rlink);
+ }
+}
+
+@ @<Print error messages about un...@>=section_check(root)
+
+@* Low-level output routines.
+The \TEX/ output is supposed to appear in lines at most |line_length|
+characters long, so we place it into an output buffer. During the output
+process, |out_line| will hold the current line number of the line about to
+be output.
+
+@<Global...@>=
+char out_buf[line_length+1]; /* assembled characters */
+char *out_ptr; /* just after last character in |out_buf| */
+char *out_buf_end = out_buf+line_length; /* end of |out_buf| */
+int out_line; /* number of next line to be output */
+
+@ The |flush_buffer| routine empties the buffer up to a given breakpoint,
+and moves any remaining characters to the beginning of the next line.
+If the |per_cent| parameter is 1 a |'%'| is appended to the line
+that is being output; in this case the breakpoint |b| should be strictly
+less than |out_buf_end|. If the |per_cent| parameter is |0|,
+trailing blanks are suppressed.
+The characters emptied from the buffer form a new line of output;
+if the |carryover| parameter is true, a |"%"| in that line will be
+carried over to the next line (so that \TEX/ will ignore the completion
+of commented-out text).
+
+@d c_line_write(c) fflush(active_file),fwrite(out_buf+1,sizeof(char),c,active_file)
+@d tex_putc(c) putc(c,active_file)
+@d tex_new_line putc('\n',active_file)
+@d tex_printf(c) fprintf(active_file,c)
+
+@c
+void
+flush_buffer(b,per_cent,carryover)
+char *b; /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */
+boolean per_cent,carryover;
+{
+ char *j; j=b; /* pointer into |out_buf| */
+ if (! per_cent) /* remove trailing blanks */
+ while (j>out_buf && *j==' ') j--;
+ c_line_write(j-out_buf);
+ if (per_cent) tex_putc('%');
+ tex_new_line; out_line++;
+ if (carryover)
+ while (j>out_buf)
+ if (*j--=='%' && (j==out_buf || *j!='\\')) {
+ *b--='%'; break;
+ }
+ if (b<out_ptr) strncpy(out_buf+1,b+1,out_ptr-b);
+ out_ptr-=b-out_buf;
+}
+
+@ When we are copying \TEX/ source material, we retain line breaks
+that occur in the input, except that an empty line is not
+output when the \TEX/ source line was nonempty. For example, a line
+of the \TEX/ file that contains only an index cross-reference entry
+will not be copied. The |finish_line| routine is called just before
+|get_line| inputs a new line, and just after a line break token has
+been emitted during the output of translated \CEE/ text.
+
+@c
+void
+finish_line() /* do this at the end of a line */
+{
+ char *k; /* pointer into |buffer| */
+ if (out_ptr>out_buf) flush_buffer(out_ptr,0,0);
+ else {
+ for (k=buffer; k<=limit; k++)
+ if (!(xisspace(*k))) return;
+ flush_buffer(out_buf,0,0);
+ }
+}
+
+@ In particular, the |finish_line| procedure is called near the very
+beginning of phase two. We initialize the output variables in a slightly
+tricky way so that the first line of the output file will be
+`\.{\\input cwebmac}'.
+
+@<Set init...@>=
+out_ptr=out_buf+1; out_line=1; active_file=tex_file;
+*out_ptr='c'; tex_printf("\\input cwebma");
+
+@ When we wish to append one character |c| to the output buffer, we write
+`|out(c)|'; this will cause the buffer to be emptied if it was already
+full. If we want to append more than one character at once, we say
+|out_str(s)|, where |s| is a string containing the characters.
+
+A line break will occur at a space or after a single-nonletter
+\TEX/ control sequence.
+
+@d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
+
+@c
+void
+out_str(s) /* output characters from |s| to end of string */
+char *s;
+{
+ while (*s) out(*s++);
+}
+
+@ The |break_out| routine is called just before the output buffer is about
+to overflow. To make this routine a little faster, we initialize position
+0 of the output buffer to `\.\\'; this character isn't really output.
+
+@<Set init...@>=
+out_buf[0]='\\';
+
+@ A long line is broken at a blank space or just before a backslash that isn't
+preceded by another backslash. In the latter case, a |'%'| is output at
+the break.
+
+@<Predecl...@>=
+void break_out();
+
+@ @c
+void
+break_out() /* finds a way to break the output line */
+{
+ char *k=out_ptr; /* pointer into |out_buf| */
+ while (1) {
+ if (k==out_buf) @<Print warning message, break the line, |return|@>;
+ if (*k==' ') {
+ flush_buffer(k,0,1); return;
+ }
+ if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */
+ flush_buffer(k,1,1); return;
+ }
+ }
+}
+
+@ We get to this section only in the unusual case that the entire output line
+consists of a string of backslashes followed by a string of nonblank
+non-backslashes. In such cases it is almost always safe to break the
+line by putting a |'%'| just before the last character.
+
+@<Print warning message...@>=
+{
+ printf("\n! Line had to be broken (output l. %d):\n",out_line);
+@.Line had to be broken@>
+ term_write(out_buf+1, out_ptr-out_buf-1);
+ new_line; mark_harmless;
+ flush_buffer(out_ptr-1,1,1); return;
+}
+
+@ Here is a macro that outputs a section number in decimal notation.
+The number to be converted by |out_section| is known to be less than
+|def_flag|, so it cannot have more than five decimal digits. If
+the section is changed, we output `\.{\\*}' just after the number.
+
+@c
+void
+out_section(n)
+sixteen_bits n;
+{
+ char s[6];
+ sprintf(s,"%d",n); out_str(s);
+ if(changed_section[n]) out_str ("\\*");
+@.\\*@>
+}
+
+@ The |out_name| procedure is used to output an identifier or index
+entry, enclosing it in braces.
+
+@c
+void
+out_name(p,quote_xalpha)
+name_pointer p;
+boolean quote_xalpha;
+{
+ char *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
+ out('{');
+ for (k=p->byte_start; k<k_end; k++) {
+ if (isxalpha(*k) && quote_xalpha) out('\\');
+@.\\\$@>
+@.\\\_@>
+ out(*k);
+ }
+ out('}');
+}
+
+@* Routines that copy \TEX/ material.
+During phase two, we use subroutines |copy_limbo|, |copy_TeX|, and
+|copy_comment| in place of the analogous |skip_limbo|, |skip_TeX|, and
+|skip_comment| that were used in phase one. (Well, |copy_comment|
+was actually written in such a way that it functions as |skip_comment|
+in phase one.)
+
+The |copy_limbo| routine, for example, takes \TEX/ material that is not
+part of any section and transcribes it almost verbatim to the output file.
+The use of `\.{@@}' signs is severely restricted in such material:
+`\.{@@@@}' pairs are replaced by singletons; `\.{@@l}' and `\.{@@q}' and
+`\.{@@s}' are interpreted.
+
+@c
+void
+copy_limbo()
+{
+ char c;
+ while (1) {
+ if (loc>limit && (finish_line(), get_line()==0)) return;
+ *(limit+1)='@@';
+ while (*loc!='@@') out(*(loc++));
+ if (loc++<=limit) {
+ c=*loc++;
+ if (ccode[(eight_bits)c]==new_section) break;
+ switch (ccode[(eight_bits)c]) {
+ case translit_code: out_str("\\ATL"); break;
+@.\\ATL@>
+ case '@@': out('@@'); break;
+ case noop: skip_restricted(); break;
+ case format_code: if (get_next()==identifier) get_next();
+ if (loc>=limit) get_line(); /* avoid blank lines in output */
+ break; /* the operands of \.{@@s} are ignored on this pass */
+ default: err_print("! Double @@ should be used in limbo");
+@.Double @@ should be used...@>
+ out('@@');
+ }
+ }
+ }
+}
+
+@ The |copy_TeX| routine processes the \TEX/ code at the beginning of a
+section; for example, the words you are now reading were copied in this
+way. It returns the next control code or `\.{\v}' found in the input.
+We don't copy spaces or tab marks into the beginning of a line. This
+makes the test for empty lines in |finish_line| work.
+
+@ @f copy_TeX TeX
+@c
+eight_bits
+copy_TeX()
+{
+ char c; /* current character being copied */
+ while (1) {
+ if (loc>limit && (finish_line(), get_line()==0)) return(new_section);
+ *(limit+1)='@@';
+ while ((c=*(loc++))!='|' && c!='@@') {
+ out(c);
+ if (out_ptr==out_buf+1 && (xisspace(c))) out_ptr--;
+ }
+ if (c=='|') return('|');
+ if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
+ }
+}
+
+@ The |copy_comment| function issues a warning if more braces are opened than
+closed, and in the case of a more serious error it supplies enough
+braces to keep \TEX/ from complaining about unbalanced braces.
+Instead of copying the \TEX/ material
+into the output buffer, this function copies it into the token memory
+(in phase two only).
+The abbreviation |app_tok(t)| is used to append token |t| to the current
+token list, and it also makes sure that it is possible to append at least
+one further token without overflow.
+
+@d app_tok(c) {if (tok_ptr+2>tok_mem_end) overflow("token"); *(tok_ptr++)=c;}
+
+@<Predec...@>=
+int copy_comment();
+
+@ @c
+int copy_comment(is_long_comment,bal) /* copies \TEX/ code in comments */
+boolean is_long_comment; /* is this a traditional \CEE/ comment? */
+int bal; /* brace balance */
+{
+ char c; /* current character being copied */
+ while (1) {
+ if (loc>limit) {
+ if (is_long_comment) {
+ if (get_line()==0) {
+ err_print("! Input ended in mid-comment");
+@.Input ended in mid-comment@>
+ loc=buffer+1; goto done;
+ }
+ }
+ else {
+ if (bal>1) err_print("! Missing } in comment");
+@.Missing \} in comment@>
+ goto done;
+ }
+ }
+ c=*(loc++);
+ if (c=='|') return(bal);
+ if (is_long_comment) @<Check for end of comment@>;
+ if (phase==2) {
+ if (ishigh(c)) app_tok(quoted_char);
+ app_tok(c);
+ }
+ @<Copy special things when |c=='@@', '\\'|@>;
+ if (c=='{') bal++;
+ else if (c=='}') {
+ if(bal>1) bal--;
+ else {err_print("! Extra } in comment");
+@.Extra \} in comment@>
+ if (phase==2) tok_ptr--;
+ }
+ }
+ }
+done:@<Clear |bal| and |return|@>;
+}
+
+@ @<Check for end of comment@>=
+if (c=='*' && *loc=='/') {
+ loc++;
+ if (bal>1) err_print("! Missing } in comment");
+@.Missing \} in comment@>
+ goto done;
+}
+
+@ @<Copy special things when |c=='@@'...@>=
+if (c=='@@') {
+ if (*(loc++)!='@@') {
+ err_print("! Illegal use of @@ in comment");
+@.Illegal use of @@...@>
+ loc-=2; if (phase==2) *(tok_ptr-1)=' '; goto done;
+ }
+}
+else if (c=='\\' && *loc!='@@')
+ if (phase==2) app_tok(*(loc++)) else loc++;
+
+@ We output
+enough right braces to keep \TEX/ happy.
+
+@<Clear |bal|...@>=
+if (phase==2) while (bal-- >0) app_tok('}');
+return(0);
+
+@** Parsing.
+The most intricate part of \.{CWEAVE} is its mechanism for converting
+\CEE/-like code into \TEX/ code, and we might as well plunge into this
+aspect of the program now. A ``bottom up'' approach is used to parse the
+\CEE/-like material, since \.{CWEAVE} must deal with fragmentary
+constructions whose overall ``part of speech'' is not known.
+
+At the lowest level, the input is represented as a sequence of entities
+that we shall call {\it scraps}, where each scrap of information consists
+of two parts, its {\it category} and its {\it translation}. The category
+is essentially a syntactic class, and the translation is a token list that
+represents \TEX/ code. Rules of syntax and semantics tell us how to
+combine adjacent scraps into larger ones, and if we are lucky an entire
+\CEE/ text that starts out as hundreds of small scraps will join
+together into one gigantic scrap whose translation is the desired \TEX/
+code. If we are unlucky, we will be left with several scraps that don't
+combine; their translations will simply be output, one by one.
+
+The combination rules are given as context-sensitive productions that are
+applied from left to right. Suppose that we are currently working on the
+sequence of scraps $s_1\,s_2\ldots s_n$. We try first to find the longest
+production that applies to an initial substring $s_1\,s_2\ldots\,$; but if
+no such productions exist, we try to find the longest production
+applicable to the next substring $s_2\,s_3\ldots\,$; and if that fails, we
+try to match $s_3\,s_4\ldots\,$, etc.
+
+A production applies if the category codes have a given pattern. For
+example, one of the productions (see rule~3) is
+$$\hbox{|exp| }\left\{\matrix{\hbox{|binop|}\cr\hbox{|ubinop|}}\right\}
+\hbox{ |exp| }\RA\hbox{ |exp|}$$
+and it means that three consecutive scraps whose respective categories are
+|exp|, |binop| (or |ubinop|),
+and |exp| are converted to one scrap whose category
+is |exp|. The translations of the original
+scraps are simply concatenated. The case of
+$$\hbox{|exp| |comma| |exp| $\RA$ |exp|} \hskip4emE_1C\,\\{opt}9\,E_2$$
+(rule 4) is only slightly more complicated:
+Here the resulting |exp| translation
+consists not only of the three original translations, but also of the
+tokens |opt| and 9 between the translations of the
+|comma| and the following |exp|.
+In the \TEX/ file, this will specify an optional line break after the
+comma, with penalty 90.
+
+At each opportunity the longest possible production is applied. For
+example, if the current sequence of scraps is |int_like| |cast|
+|lbrace|, rule 31 is applied; but if the sequence is |int_like| |cast|
+followed by anything other than |lbrace|, rule 32 takes effect.
+
+Translation rules such as `$E_1C\,\\{opt}9\,E_2$' above use subscripts
+to distinguish between translations of scraps whose categories have the
+same initial letter; these subscripts are assigned from left to right.
+
+@ Here is a list of the category codes that scraps can have.
+(A few others, like |int_like|, have already been defined; the
+|cat_name| array contains a complete list.)
+
+@d exp 1 /* denotes an expression, including perhaps a single identifier */
+@d unop 2 /* denotes a unary operator */
+@d binop 3 /* denotes a binary operator */
+@d ubinop 4
+ /* denotes an operator that can be unary or binary, depending on context */
+@d cast 5 /* denotes a cast */
+@d question 6 /* denotes a question mark and possibly the expressions flanking it */
+@d lbrace 7 /* denotes a left brace */
+@d rbrace 8 /* denotes a right brace */
+@d decl_head 9 /* denotes an incomplete declaration */
+@d comma 10 /* denotes a comma */
+@d lpar 11 /* denotes a left parenthesis or left bracket */
+@d rpar 12 /* denotes a right parenthesis or right bracket */
+@d prelangle 13 /* denotes `$<$' before we know what it is */
+@d prerangle 14 /* denotes `$>$' before we know what it is */
+@d langle 15 /* denotes `$<$' when it's used as angle bracket in a template */
+@d colcol 18 /* denotes `::' */
+@d base 19 /* denotes a colon that introduces a base specifier */
+@d decl 20 /* denotes a complete declaration */
+@d struct_head 21 /* denotes the beginning of a structure specifier */
+@d stmt 23 /* denotes a complete statement */
+@d function 24 /* denotes a complete function */
+@d fn_decl 25 /* denotes a function declarator */
+@d semi 27 /* denotes a semicolon */
+@d colon 28 /* denotes a colon */
+@d tag 29 /* denotes a statement label */
+@d if_head 30 /* denotes the beginning of a compound conditional */
+@d else_head 31 /* denotes a prefix for a compound statement */
+@d if_clause 32 /* pending \.{if} together with a condition */
+@d lproc 35 /* begins a preprocessor command */
+@d rproc 36 /* ends a preprocessor command */
+@d insert 37 /* a scrap that gets combined with its neighbor */
+@d section_scrap 38 /* section name */
+@d dead 39 /* scrap that won't combine */
+@d ftemplate 59 /* \\{make\_pair} */
+@d new_exp 60 /* \&{new} and a following type identifier */
+@d begin_arg 61 /* \.{@@[} */
+@d end_arg 62 /* \.{@@]} */
+
+@<Glo...@>=
+char cat_name[256][12];
+eight_bits cat_index;
+
+@ @<Set in...@>=
+ for (cat_index=0;cat_index<255;cat_index++)
+ strcpy(cat_name[cat_index],"UNKNOWN");
+@.UNKNOWN@>
+ strcpy(cat_name[exp],"exp");
+ strcpy(cat_name[unop],"unop");
+ strcpy(cat_name[binop],"binop");
+ strcpy(cat_name[ubinop],"ubinop");
+ strcpy(cat_name[cast],"cast");
+ strcpy(cat_name[question],"?");
+ strcpy(cat_name[lbrace],"{"@q}@>);
+ strcpy(cat_name[rbrace],@q{@>"}");
+ strcpy(cat_name[decl_head],"decl_head");
+ strcpy(cat_name[comma],",");
+ strcpy(cat_name[lpar],"(");
+ strcpy(cat_name[rpar],")");
+ strcpy(cat_name[prelangle],"<");
+ strcpy(cat_name[prerangle],">");
+ strcpy(cat_name[langle],"\\<");
+ strcpy(cat_name[colcol],"::");
+ strcpy(cat_name[base],"\\:");
+ strcpy(cat_name[decl],"decl");
+ strcpy(cat_name[struct_head],"struct_head");
+ strcpy(cat_name[alfop],"alfop");
+ strcpy(cat_name[stmt],"stmt");
+ strcpy(cat_name[function],"function");
+ strcpy(cat_name[fn_decl],"fn_decl");
+ strcpy(cat_name[else_like],"else_like");
+ strcpy(cat_name[semi],";");
+ strcpy(cat_name[colon],":");
+ strcpy(cat_name[tag],"tag");
+ strcpy(cat_name[if_head],"if_head");
+ strcpy(cat_name[else_head],"else_head");
+ strcpy(cat_name[if_clause],"if()");
+ strcpy(cat_name[lproc],"#{"@q}@>);
+ strcpy(cat_name[rproc],@q{@>"#}");
+ strcpy(cat_name[insert],"insert");
+ strcpy(cat_name[section_scrap],"section");
+ strcpy(cat_name[dead],"@@d");
+ strcpy(cat_name[public_like],"public");
+ strcpy(cat_name[operator_like],"operator");
+ strcpy(cat_name[new_like],"new");
+ strcpy(cat_name[catch_like],"catch");
+ strcpy(cat_name[for_like],"for");
+ strcpy(cat_name[do_like],"do");
+ strcpy(cat_name[if_like],"if");
+ strcpy(cat_name[delete_like],"delete");
+ strcpy(cat_name[raw_ubin],"ubinop?");
+ strcpy(cat_name[const_like],"const");
+ strcpy(cat_name[raw_int],"raw");
+ strcpy(cat_name[int_like],"int");
+ strcpy(cat_name[case_like],"case");
+ strcpy(cat_name[sizeof_like],"sizeof");
+ strcpy(cat_name[struct_like],"struct");
+ strcpy(cat_name[typedef_like],"typedef");
+ strcpy(cat_name[define_like],"define");
+ strcpy(cat_name[template_like],"template");
+ strcpy(cat_name[ftemplate],"ftemplate");
+ strcpy(cat_name[new_exp],"new_exp");
+ strcpy(cat_name[begin_arg],"@@["@q]@>);
+ strcpy(cat_name[end_arg],@q[@>"@@]");
+ strcpy(cat_name[0],"zero");
+
+@ This code allows \.{CWEAVE} to display its parsing steps.
+
+@c
+void
+print_cat(c) /* symbolic printout of a category */
+eight_bits c;
+{
+ printf(cat_name[c]);
+}
+
+@ The token lists for translated \TEX/ output contain some special control
+symbols as well as ordinary characters. These control symbols are
+interpreted by \.{CWEAVE} before they are written to the output file.
+
+\yskip\hang |break_space| denotes an optional line break or an en space;
+
+\yskip\hang |force| denotes a line break;
+
+\yskip\hang |big_force| denotes a line break with additional vertical space;
+
+\yskip\hang |preproc_line| denotes that the line will be printed flush left;
+
+\yskip\hang |opt| denotes an optional line break (with the continuation
+line indented two ems with respect to the normal starting position)---this
+code is followed by an integer |n|, and the break will occur with penalty
+$10n$;
+
+\yskip\hang |backup| denotes a backspace of one em;
+
+\yskip\hang |cancel| obliterates any |break_space|, |opt|, |force|, or
+|big_force| tokens that immediately precede or follow it and also cancels any
+|backup| tokens that follow it;
+
+\yskip\hang |indent| causes future lines to be indented one more em;
+
+\yskip\hang |outdent| causes future lines to be indented one less em.
+
+\yskip\noindent All of these tokens are removed from the \TEX/ output that
+comes from \CEE/ text between \pb\ signs; |break_space| and |force| and
+|big_force| become single spaces in this mode. The translation of other
+\CEE/ texts results in \TEX/ control sequences \.{\\1}, \.{\\2},
+\.{\\3}, \.{\\4}, \.{\\5}, \.{\\6}, \.{\\7}, \.{\\8}
+corresponding respectively to
+|indent|, |outdent|, |opt|, |backup|, |break_space|, |force|,
+|big_force| and |preproc_line|.
+However, a sequence of consecutive `\.\ ', |break_space|,
+|force|, and/or |big_force| tokens is first replaced by a single token
+(the maximum of the given ones).
+
+The token |math_rel| will be translated into
+\.{\\MRL\{}, and it will get a matching \.\} later.
+Other control sequences in the \TEX/ output will be
+`\.{\\\\\{}$\,\ldots\,$\.\}'
+surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
+reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
+`\.{\\C\{}$\,\ldots\,$\.\}$\,$|force|' surrounding comments, and
+`\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding section names, where
+|n| is the section number.
+
+@d math_rel 0206
+@d big_cancel 0210 /* like |cancel|, also overrides spaces */
+@d cancel 0211 /* overrides |backup|, |break_space|, |force|, |big_force| */
+@d indent 0212 /* one more tab (\.{\\1}) */
+@d outdent 0213 /* one less tab (\.{\\2}) */
+@d opt 0214 /* optional break in mid-statement (\.{\\3}) */
+@d backup 0215 /* stick out one unit to the left (\.{\\4}) */
+@d break_space 0216 /* optional break between statements (\.{\\5}) */
+@d force 0217 /* forced break between statements (\.{\\6}) */
+@d big_force 0220 /* forced break with additional space (\.{\\7}) */
+@d preproc_line 0221 /* begin line without indentation (\.{\\8}) */
+@^high-bit character handling@>
+@d quoted_char 0222
+ /* introduces a character token in the range |0200|--|0377| */
+@d end_translation 0223 /* special sentinel token at end of list */
+@d inserted 0224 /* sentinel to mark translations of inserts */
+@d qualifier 0225 /* introduces an explicit namespace qualifier */
+
+@ The raw input is converted into scraps according to the following table,
+which gives category codes followed by the translations.
+\def\stars {\.{**}}%
+The symbol `\stars' stands for `\.{\\\&\{{\rm identifier}\}}',
+i.e., the identifier itself treated as a reserved word.
+The right-hand column is the so-called |mathness|, which is explained
+further below.
+
+An identifier |c| of length 1 is translated as \.{\\\v c} instead of
+as \.{\\\\\{c\}}. An identifier \.{CAPS} in all caps is translated as
+\.{\\.\{CAPS\}} instead of as \.{\\\\\{CAPS\}}. An identifier that has
+become a reserved word via |typedef| is translated with \.{\\\&} replacing
+\.{\\\\} and |raw_int| replacing |exp|.
+
+A string of length greater than 20 is broken into pieces of size at most~20
+with discretionary breaks in between.
+
+\yskip\halign{\quad#\hfil&\quad#\hfil&\quad\hfil#\hfil\cr
+\.{!=}&|binop|: \.{\\I}&yes\cr
+\.{<=}&|binop|: \.{\\Z}&yes\cr
+\.{>=}&|binop|: \.{\\G}&yes\cr
+\.{==}&|binop|: \.{\\E}&yes\cr
+\.{\&\&}&|binop|: \.{\\W}&yes\cr
+\.{\v\v}&|binop|: \.{\\V}&yes\cr
+\.{++}&|unop|: \.{\\PP}&yes\cr
+\.{--}&|unop|: \.{\\MM}&yes\cr
+\.{->}&|binop|: \.{\\MG}&yes\cr
+\.{>>}&|binop|: \.{\\GG}&yes\cr
+\.{<<}&|binop|: \.{\\LL}&yes\cr
+\.{::}&|colcol|: \.{\\DC}&maybe\cr
+\.{.*}&|binop|: \.{\\PA}&yes\cr
+\.{->*}&|binop|: \.{\\MGA}&yes\cr
+\.{...}&|raw_int|: \.{\\,\\ldots\\,}&yes\cr
+\."string\."&|exp|: \.{\\.\{}string with special characters quoted\.\}&maybe\cr
+\.{@@=}string\.{@@>}&|exp|: \.{\\vb\{}string with special characters
+ quoted\.\}&maybe\cr
+\.{@@'7'}&|exp|: \.{\\.\{@@'7'\}}&maybe\cr
+\.{077} or \.{\\77}&|exp|: \.{\\T\{\\\~77\}}&maybe\cr
+\.{0x7f}&|exp|: \.{\\T\{\\\^7f\}}&maybe\cr
+\.{77}&|exp|: \.{\\T\{77\}}&maybe\cr
+\.{77L}&|exp|: \.{\\T\{77\\\$L\}}&maybe\cr
+\.{0.1E5}&|exp|: \.{\\T\{0.1\\\_5\}}&maybe\cr
+\.+&|ubinop|: \.+&yes\cr
+\.-&|ubinop|: \.-&yes\cr
+\.*&|raw_ubin|: \.*&yes\cr
+\./&|binop|: \./&yes\cr
+\.<&|prelangle|: \.{\\langle}&yes\cr
+\.=&|binop|: \.{\\K}&yes\cr
+\.>&|prerangle|: \.{\\rangle}&yes\cr
+\..&|binop|: \..&yes\cr
+\.{\v}&|binop|: \.{\\OR}&yes\cr
+\.\^&|binop|: \.{\\XOR}&yes\cr
+\.\%&|binop|: \.{\\MOD}&yes\cr
+\.?&|question|: \.{\\?}&yes\cr
+\.!&|unop|: \.{\\R}&yes\cr
+\.\~&|unop|: \.{\\CM}&yes\cr
+\.\&&|raw_ubin|: \.{\\AND}&yes\cr
+\.(&|lpar|: \.(&maybe\cr
+\.[&|lpar|: \.[&maybe\cr
+\.)&|rpar|: \.)&maybe\cr
+\.]&|rpar|: \.]&maybe\cr
+\.\{&|lbrace|: \.\{&yes\cr
+\.\}&|lbrace|: \.\}&yes\cr
+\.,&|comma|: \.,&yes\cr
+\.;&|semi|: \.;&maybe\cr
+\.:&|colon|: \.:&no\cr
+\.\# (within line)&|ubinop|: \.{\\\#}&yes\cr
+\.\# (at beginning)&|lproc|: |force| |preproc_line| \.{\\\#}&no\cr
+end of \.\# line&|rproc|: |force|&no\cr
+identifier&|exp|: \.{\\\\\{}identifier with underlines and
+ dollar signs quoted\.\}&maybe\cr
+\.{and}&|alfop|: \stars&yes\cr
+\.{and\_eq}&|alfop|: \stars&yes\cr
+\.{asm}&|sizeof_like|: \stars&maybe\cr
+\.{auto}&|int_like|: \stars&maybe\cr
+\.{bitand}&|alfop|: \stars&yes\cr
+\.{bitor}&|alfop|: \stars&yes\cr
+\.{bool}&|raw_int|: \stars&maybe\cr
+\.{break}&|case_like|: \stars&maybe\cr
+\.{case}&|case_like|: \stars&maybe\cr
+\.{catch}&|catch_like|: \stars&maybe\cr
+\.{char}&|raw_int|: \stars&maybe\cr
+\.{class}&|struct_like|: \stars&maybe\cr
+\.{clock\_t}&|raw_int|: \stars&maybe\cr
+\.{compl}&|alfop|: \stars&yes\cr
+\.{const}&|const_like|: \stars&maybe\cr
+\.{const\_cast}&|raw_int|: \stars&maybe\cr
+\.{continue}&|case_like|: \stars&maybe\cr
+\.{default}&|case_like|: \stars&maybe\cr
+\.{define}&|define_like|: \stars&maybe\cr
+\.{defined}&|sizeof_like|: \stars&maybe\cr
+\.{delete}&|delete_like|: \stars&maybe\cr
+\.{div\_t}&|raw_int|: \stars&maybe\cr
+\.{do}&|do_like|: \stars&maybe\cr
+\.{double}&|raw_int|: \stars&maybe\cr
+\.{dynamic\_cast}&|raw_int|: \stars&maybe\cr
+\.{elif}&|if_like|: \stars&maybe\cr
+\.{else}&|else_like|: \stars&maybe\cr
+\.{endif}&|if_like|: \stars&maybe\cr
+\.{enum}&|struct_like|: \stars&maybe\cr
+\.{error}&|if_like|: \stars&maybe\cr
+\.{explicit}&|int_like|: \stars&maybe\cr
+\.{export}&|int_like|: \stars&maybe\cr
+\.{extern}&|int_like|: \stars&maybe\cr
+\.{FILE}&|raw_int|: \stars&maybe\cr
+\.{float}&|raw_int|: \stars&maybe\cr
+\.{for}&|for_like|: \stars&maybe\cr
+\.{fpos\_t}&|raw_int|: \stars&maybe\cr
+\.{friend}&|int_like|: \stars&maybe\cr
+\.{goto}&|case_like|: \stars&maybe\cr
+\.{if}&|if_like|: \stars&maybe\cr
+\.{ifdef}&|if_like|: \stars&maybe\cr
+\.{ifndef}&|if_like|: \stars&maybe\cr
+\.{include}&|if_like|: \stars&maybe\cr
+\.{inline}&|int_like|: \stars&maybe\cr
+\.{int}&|raw_int|: \stars&maybe\cr
+\.{jmp\_buf}&|raw_int|: \stars&maybe\cr
+\.{ldiv\_t}&|raw_int|: \stars&maybe\cr
+\.{line}&|if_like|: \stars&maybe\cr
+\.{long}&|raw_int|: \stars&maybe\cr
+\.{make\_pair}&|ftemplate|: \.{\\\\\{make\\\_pair\}}&maybe\cr
+\.{mutable}&|int_like|: \stars&maybe\cr
+\.{namespace}&|struct_like|: \stars&maybe\cr
+\.{new}&|new_like|: \stars&maybe\cr
+\.{not}&|alfop|: \stars&yes\cr
+\.{not\_eq}&|alfop|: \stars&yes\cr
+\.{NULL}&|exp|: \.{\\NULL}&yes\cr
+\.{offsetof}&|raw_int|: \stars&maybe\cr
+\.{operator}&|operator_like|: \stars&maybe\cr
+\.{or}&|alfop|: \stars&yes\cr
+\.{or\_eq}&|alfop|: \stars&yes\cr
+\.{pragma}&|if_like|: \stars&maybe\cr
+\.{private}&|public_like|: \stars&maybe\cr
+\.{protected}&|public_like|: \stars&maybe\cr
+\.{ptrdiff\_t}&|raw_int|: \stars&maybe\cr
+\.{public}&|public_like|: \stars&maybe\cr
+\.{register}&|int_like|: \stars&maybe\cr
+\.{reinterpret\_cast}&|raw_int|: \stars&maybe\cr
+\.{return}&|case_like|: \stars&maybe\cr
+\.{short}&|raw_int|: \stars&maybe\cr
+\.{sig\_atomic\_t}&|raw_int|: \stars&maybe\cr
+\.{signed}&|raw_int|: \stars&maybe\cr
+\.{size\_t}&|raw_int|: \stars&maybe\cr
+\.{sizeof}&|sizeof_like|: \stars&maybe\cr
+\.{static}&|int_like|: \stars&maybe\cr
+\.{static\_cast}&|raw_int|: \stars&maybe\cr
+\.{struct}&|struct_like|: \stars&maybe\cr
+\.{switch}&|for_like|: \stars&maybe\cr
+\.{template}&|template_like|: \stars&maybe\cr
+\.{TeX}&|exp|: \.{\\TeX}&yes\cr
+\.{this}&|exp|: \.{\\this}&yes\cr
+\.{throw}&|case_like|: \stars&maybe\cr
+\.{time\_t}&|raw_int|: \stars&maybe\cr
+\.{try}&|else_like|: \stars&maybe\cr
+\.{typedef}&|typedef_like|: \stars&maybe\cr
+\.{typeid}&|raw_int|: \stars&maybe\cr
+\.{typename}&|struct_like|: \stars&maybe\cr
+\.{undef}&|if_like|: \stars&maybe\cr
+\.{union}&|struct_like|: \stars&maybe\cr
+\.{unsigned}&|raw_int|: \stars&maybe\cr
+\.{using}&|int_like|: \stars&maybe\cr
+\.{va\_dcl}&|decl|: \stars&maybe\cr
+\.{va\_list}&|raw_int|: \stars&maybe\cr
+\.{virtual}&|int_like|: \stars&maybe\cr
+\.{void}&|raw_int|: \stars&maybe\cr
+\.{volatile}&|const_like|: \stars&maybe\cr
+\.{wchar\_t}&|raw_int|: \stars&maybe\cr
+\.{while}&|for_like|: \stars&maybe\cr
+\.{xor}&|alfop|: \stars&yes\cr
+\.{xor\_eq}&|alfop|: \stars&yes\cr
+\.{@@,}&|insert|: \.{\\,}&maybe\cr
+\.{@@\v}&|insert|: |opt| \.0&maybe\cr
+\.{@@/}&|insert|: |force|&no\cr
+\.{@@\#}&|insert|: |big_force|&no\cr
+\.{@@+}&|insert|: |big_cancel| \.{\{\}} |break_space|
+ \.{\{\}} |big_cancel|&no\cr
+\.{@@;}&|semi|: &maybe\cr
+\.{@@[@q]@>}&|begin_arg|: &maybe\cr
+\.{@q[@>@@]}&|end_arg|: &maybe\cr
+\.{@@\&}&|insert|: \.{\\J}&maybe\cr
+\.{@@h}&|insert|: |force| \.{\\ATH} |force|&no\cr
+\.{@@<}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
+ \.{\\X}$n$\.:translated section name\.{\\X}&maybe\cr
+\.{@@(@q)@>}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
+ \.{\\X}$n$\.{:\\.\{}section name with special characters
+ quoted\.{\ \}\\X}&maybe\cr
+\.{/*}comment\.{*/}&|insert|: |cancel|
+ \.{\\C\{}translated comment\.\} |force|&no\cr
+\.{//}comment&|insert|: |cancel|
+ \.{\\SHC\{}translated comment\.\} |force|&no\cr
+}
+
+\smallskip
+The construction \.{@@t}\thinspace stuff\/\thinspace\.{@@>} contributes
+\.{\\hbox\{}\thinspace stuff\/\thinspace\.\} to the following scrap.
+
+@i prod.w
+
+@* Implementing the productions.
+More specifically, a scrap is a structure consisting of a category
+|cat| and a |text_pointer| |trans|, which points to the translation in
+|tok_start|. When \CEE/ text is to be processed with the grammar above,
+we form an array |scrap_info| containing the initial scraps.
+Our production rules have the nice property that the right-hand side is never
+longer than the left-hand side. Therefore it is convenient to use sequential
+allocation for the current sequence of scraps. Five pointers are used to
+manage the parsing:
+
+\yskip\hang |pp| is a pointer into |scrap_info|. We will try to match
+the category codes |pp->cat,@,@,(pp+1)->cat|$,\,\,\ldots\,$
+to the left-hand sides of productions.
+
+\yskip\hang |scrap_base|, |lo_ptr|, |hi_ptr|, and |scrap_ptr| are such that
+the current sequence of scraps appears in positions |scrap_base| through
+|lo_ptr| and |hi_ptr| through |scrap_ptr|, inclusive, in the |cat| and
+|trans| arrays. Scraps located between |scrap_base| and |lo_ptr| have
+been examined, while those in positions |>=hi_ptr| have not yet been
+looked at by the parsing process.
+
+\yskip\noindent Initially |scrap_ptr| is set to the position of the final
+scrap to be parsed, and it doesn't change its value. The parsing process
+makes sure that |lo_ptr>=pp+3|, since productions have as many as four terms,
+by moving scraps from |hi_ptr| to |lo_ptr|. If there are
+fewer than |pp+3| scraps left, the positions up to |pp+3| are filled with
+blanks that will not match in any productions. Parsing stops when
+|pp==lo_ptr+1| and |hi_ptr==scrap_ptr+1|.
+
+Since the |scrap| structure will later be used for other purposes, we
+declare its second element as a union.
+
+@<Type...@>=
+typedef struct {
+ eight_bits cat;
+ eight_bits mathness;
+ union {
+ text_pointer Trans;
+ @<Rest of |trans_plus| union@>@;
+ } trans_plus;
+} scrap;
+typedef scrap *scrap_pointer;
+
+@ @d trans trans_plus.Trans /* translation texts of scraps */
+
+@<Global...@>=
+scrap scrap_info[max_scraps]; /* memory array for scraps */
+scrap_pointer scrap_info_end=scrap_info+max_scraps -1; /* end of |scrap_info| */
+scrap_pointer pp; /* current position for reducing productions */
+scrap_pointer scrap_base; /* beginning of the current scrap sequence */
+scrap_pointer scrap_ptr; /* ending of the current scrap sequence */
+scrap_pointer lo_ptr; /* last scrap that has been examined */
+scrap_pointer hi_ptr; /* first scrap that has not been examined */
+scrap_pointer max_scr_ptr; /* largest value assumed by |scrap_ptr| */
+
+@ @<Set init...@>=
+scrap_base=scrap_info+1;
+max_scr_ptr=scrap_ptr=scrap_info;
+
+@ Token lists in |@!tok_mem| are composed of the following kinds of
+items for \TEX/ output.
+
+\yskip\item{$\bullet$}Character codes and special codes like |force| and
+|math_rel| represent themselves;
+
+\item{$\bullet$}|id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|section_flag+p| represents section name |p|;
+
+\item{$\bullet$}|tok_flag+p| represents token list number |p|;
+
+\item{$\bullet$}|inner_tok_flag+p| represents token list number |p|, to be
+translated without line-break controls.
+
+@d id_flag 10240 /* signifies an identifier */
+@d res_flag 2*id_flag /* signifies a reserved word */
+@d section_flag 3*id_flag /* signifies a section name */
+@d tok_flag 4*id_flag /* signifies a token list */
+@d inner_tok_flag 5*id_flag /* signifies a token list in `\pb' */
+
+@c
+void
+print_text(p) /* prints a token list for debugging; not used in |main| */
+text_pointer p;
+{
+ token_pointer j; /* index into |tok_mem| */
+ sixteen_bits r; /* remainder of token after the flag has been stripped off */
+ if (p>=text_ptr) printf("BAD");
+ else for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+ switch (*j/id_flag) {
+ case 1: printf("\\\\{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
+ break; /* |id_flag| */
+ case 2: printf("\\&{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
+ break; /* |res_flag| */
+ case 3: printf("<"); print_section_name((name_dir+r)); printf(">");
+ break; /* |section_flag| */
+ case 4: printf("[[%d]]",r); break; /* |tok_flag| */
+ case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
+ default: @<Print token |r| in symbolic form@>;
+ }
+ }
+ fflush(stdout);
+}
+
+@ @<Print token |r|...@>=
+switch (r) {
+ case math_rel: printf("\\mathrel{"@q}@>); break;
+ case big_cancel: printf("[ccancel]"); break;
+ case cancel: printf("[cancel]"); break;
+ case indent: printf("[indent]"); break;
+ case outdent: printf("[outdent]"); break;
+ case backup: printf("[backup]"); break;
+ case opt: printf("[opt]"); break;
+ case break_space: printf("[break]"); break;
+ case force: printf("[force]"); break;
+ case big_force: printf("[fforce]"); break;
+ case preproc_line: printf("[preproc]"); break;
+ case quoted_char: j++; printf("[%o]",(unsigned)*j); break;
+ case end_translation: printf("[quit]"); break;
+ case inserted: printf("[inserted]"); break;
+ default: putxchar(r);
+}
+
+@ The production rules listed above are embedded directly into \.{CWEAVE},
+since it is easier to do this than to write an interpretive system
+that would handle production systems in general. Several macros are defined
+here so that the program for each production is fairly short.
+
+All of our productions conform to the general notion that some |k|
+consecutive scraps starting at some position |j| are to be replaced by a
+single scrap of some category |c| whose translation is composed from the
+translations of the disappearing scraps. After this production has been
+applied, the production pointer |pp| should change by an amount |d|. Such
+a production can be represented by the quadruple |(j,k,c,d)|. For example,
+the production `|exp@,comma@,exp| $\RA$ |exp|' would be represented by
+`|(pp,3,exp,-2)|'; in this case the pointer |pp| should decrease by 2
+after the production has been applied, because some productions with
+|exp| in their second or third positions might now match,
+but no productions have
+|exp| in the fourth position of their left-hand sides. Note that
+the value of |d| is determined by the whole collection of productions, not
+by an individual one.
+The determination of |d| has been
+done by hand in each case, based on the full set of productions but not on
+the grammar of \CEE/ or on the rules for constructing the initial
+scraps.
+
+We also attach a serial number to each production, so that additional
+information is available when debugging. For example, the program below
+contains the statement `|reduce(pp,3,exp,-2,4)|' when it implements
+the production just mentioned.
+
+Before calling |reduce|, the program should have appended the tokens of
+the new translation to the |tok_mem| array. We commonly want to append
+copies of several existing translations, and macros are defined to
+simplify these common cases. For example, \\{app2}|(pp)| will append the
+translations of two consecutive scraps, |pp->trans| and |(pp+1)->trans|, to
+the current token list. If the entire new translation is formed in this
+way, we write `|squash(j,k,c,d,n)|' instead of `|reduce(j,k,c,d,n)|'. For
+example, `|squash(pp,3,exp,-2,3)|' is an abbreviation for `\\{app3}|(pp);
+reduce(pp,3,exp,-2,3)|'.
+
+A couple more words of explanation:
+Both |big_app| and |app| append a token (while |big_app1| to |big_app4|
+append the specified number of scrap translations) to the current token list.
+The difference between |big_app| and |app| is simply that |big_app|
+checks whether there can be a conflict between math and non-math
+tokens, and intercalates a `\.{\$}' token if necessary. When in
+doubt what to use, use |big_app|.
+
+The |mathness| is an attribute of scraps that says whether they are
+to be printed in a math mode context or not. It is separate from the
+``part of speech'' (the |cat|) because to make each |cat| have
+a fixed |mathness| (as in the original \.{WEAVE}) would multiply the
+number of necessary production rules.
+
+The low two bits (i.e. |mathness % 4|) control the left boundary.
+(We need two bits because we allow cases |yes_math|, |no_math| and
+|maybe_math|, which can go either way.)
+The next two bits (i.e. |mathness / 4|) control the right boundary.
+If we combine two scraps and the right boundary of the first has
+a different mathness from the left boundary of the second, we
+insert a \.{\$} in between. Similarly, if at printing time some
+irreducible scrap has a |yes_math| boundary the scrap gets preceded
+or followed by a \.{\$}. The left boundary is |maybe_math| if and
+only if the right boundary is.
+
+The code below is an exact translation of the production rules into
+\CEE/, using such macros, and the reader should have no difficulty
+understanding the format by comparing the code with the symbolic
+productions as they were listed earlier.
+
+@d no_math 2 /* should be in horizontal mode */
+@d yes_math 1 /* should be in math mode */
+@d maybe_math 0 /* works in either horizontal or math mode */
+@d big_app2(a) big_app1(a);big_app1(a+1)
+@d big_app3(a) big_app2(a);big_app1(a+2)
+@d big_app4(a) big_app3(a);big_app1(a+3)
+@d app(a) *(tok_ptr++)=a
+@d app1(a) *(tok_ptr++)=tok_flag+(int)((a)->trans-tok_start)
+
+@<Global...@>=
+int cur_mathness, init_mathness;
+
+@ @c
+void
+app_str(s)
+char *s;
+{
+ while (*s) app_tok(*(s++));
+}
+
+void
+big_app(a)
+token a;
+{
+ if (a==' ' || (a>=big_cancel && a<=big_force)) /* non-math token */ {
+ if (cur_mathness==maybe_math) init_mathness=no_math;
+ else if (cur_mathness==yes_math) app_str("{}$");
+ cur_mathness=no_math;
+ }
+ else {
+ if (cur_mathness==maybe_math) init_mathness=yes_math;
+ else if (cur_mathness==no_math) app_str("${}");
+ cur_mathness=yes_math;
+ }
+ app(a);
+}
+
+void
+big_app1(a)
+scrap_pointer a;
+{
+ switch (a->mathness % 4) { /* left boundary */
+ case (no_math):
+ if (cur_mathness==maybe_math) init_mathness=no_math;
+ else if (cur_mathness==yes_math) app_str("{}$");
+ cur_mathness=a->mathness / 4; /* right boundary */
+ break;
+ case (yes_math):
+ if (cur_mathness==maybe_math) init_mathness=yes_math;
+ else if (cur_mathness==no_math) app_str("${}");
+ cur_mathness=a->mathness / 4; /* right boundary */
+ break;
+ case (maybe_math): /* no changes */ break;
+ }
+ app(tok_flag+(int)((a)->trans-tok_start));
+}
+
+@ Let us consider the big switch for productions now, before looking
+at its context. We want to design the program so that this switch
+works, so we might as well not keep ourselves in suspense about exactly what
+code needs to be provided with a proper environment.
+
+@d cat1 (pp+1)->cat
+@d cat2 (pp+2)->cat
+@d cat3 (pp+3)->cat
+@d lhs_not_simple (pp->cat!=public_like
+ && pp->cat!=semi
+ && pp->cat!=prelangle
+ && pp->cat!=prerangle
+ && pp->cat!=template_like
+ && pp->cat!=new_like
+ && pp->cat!=new_exp
+ && pp->cat!=ftemplate
+ && pp->cat!=raw_ubin
+ && pp->cat!=const_like
+ && pp->cat!=raw_int
+ && pp->cat!=operator_like)
+ /* not a production with left side length 1 */
+
+@<Match a production at |pp|, or increase |pp| if there is no match@>= {
+ if (cat1==end_arg && lhs_not_simple)
+ if (pp->cat==begin_arg) squash(pp,2,exp,-2,124);
+ else squash(pp,2,end_arg,-1,125);
+ else if (cat1==insert) squash(pp,2,pp->cat,-2,0);
+ else if (cat2==insert) squash(pp+1,2,(pp+1)->cat,-1,0);
+ else if (cat3==insert) squash(pp+2,2,(pp+2)->cat,0,0);
+ else
+ switch (pp->cat) {
+ case exp: @<Cases for |exp|@>; @+break;
+ case lpar: @<Cases for |lpar|@>; @+break;
+ case unop: @<Cases for |unop|@>; @+break;
+ case ubinop: @<Cases for |ubinop|@>; @+break;
+ case binop: @<Cases for |binop|@>; @+break;
+ case cast: @<Cases for |cast|@>; @+break;
+ case sizeof_like: @<Cases for |sizeof_like|@>; @+break;
+ case int_like: @<Cases for |int_like|@>; @+break;
+ case public_like: @<Cases for |public_like|@>; @+break;
+ case colcol: @<Cases for |colcol|@>; @+break;
+ case decl_head: @<Cases for |decl_head|@>; @+break;
+ case decl: @<Cases for |decl|@>; @+break;
+ case base: @<Cases for |base|@>; @+break;
+ case struct_like: @<Cases for |struct_like|@>; @+break;
+ case struct_head: @<Cases for |struct_head|@>; @+break;
+ case fn_decl: @<Cases for |fn_decl|@>; @+break;
+ case function: @<Cases for |function|@>; @+break;
+ case lbrace: @<Cases for |lbrace|@>; @+break;
+ case if_like: @<Cases for |if_like|@>; @+break;
+ case else_like: @<Cases for |else_like|@>; @+break;
+ case else_head: @<Cases for |else_head|@>; @+break;
+ case if_clause: @<Cases for |if_clause|@>; @+break;
+ case if_head: @<Cases for |if_head|@>; @+break;
+ case do_like: @<Cases for |do_like|@>; @+break;
+ case case_like: @<Cases for |case_like|@>; @+break;
+ case catch_like: @<Cases for |catch_like|@>; @+break;
+ case tag: @<Cases for |tag|@>; @+break;
+ case stmt: @<Cases for |stmt|@>; @+break;
+ case semi: @<Cases for |semi|@>; @+break;
+ case lproc: @<Cases for |lproc|@>; @+break;
+ case section_scrap: @<Cases for |section_scrap|@>; @+break;
+ case insert: @<Cases for |insert|@>; @+break;
+ case prelangle: @<Cases for |prelangle|@>; @+break;
+ case prerangle: @<Cases for |prerangle|@>; @+break;
+ case langle: @<Cases for |langle|@>; @+break;
+ case template_like: @<Cases for |template_like|@>; @+break;
+ case new_like: @<Cases for |new_like|@>; @+break;
+ case new_exp: @<Cases for |new_exp|@>; @+break;
+ case ftemplate: @<Cases for |ftemplate|@>; @+break;
+ case for_like: @<Cases for |for_like|@>; @+break;
+ case raw_ubin: @<Cases for |raw_ubin|@>; @+break;
+ case const_like: @<Cases for |const_like|@>; @+break;
+ case raw_int: @<Cases for |raw_int|@>; @+break;
+ case operator_like: @<Cases for |operator_like|@>; @+break;
+ case typedef_like: @<Cases for |typedef_like|@>; @+break;
+ case delete_like: @<Cases for |delete_like|@>; @+break;
+ case question: @<Cases for |question|@>; @+break;
+ }
+ pp++; /* if no match was found, we move to the right */
+}
+
+@ In \CEE/, new specifier names can be defined via |typedef|, and we want
+to make the parser recognize future occurrences of the identifier thus
+defined as specifiers. This is done by the procedure |make_reserved|,
+which changes the |ilk| of the relevant identifier.
+
+We first need a procedure to recursively seek the first
+identifier in a token list, because the identifier might
+be enclosed in parentheses, as when one defines a function
+returning a pointer.
+
+If the first identifier found is a keyword like `\&{case}', we
+return the special value |case_found|; this prevents underlining
+of identifiers in case labels.
+
+If the first identifier is the keyword `\&{operator}', we give up;
+users who want to index definitions of overloaded \CPLUSPLUS/ operators
+should say, for example, `\.{@@!@@\^\\\&\{operator\} \$+\{=\}\$@@>}' (or,
+more properly alphebetized,
+`\.{@@!@@:operator+=\}\{\\\&\{operator\} \$+\{=\}\$@@>}').
+
+@d no_ident_found (token_pointer)0 /* distinct from any identifier token */
+@d case_found (token_pointer)1 /* likewise */
+@d operator_found (token_pointer)2 /* likewise */
+
+@c
+token_pointer
+find_first_ident(p)
+text_pointer p;
+{
+ token_pointer q; /* token to be returned */
+ token_pointer j; /* token being looked at */
+ sixteen_bits r; /* remainder of token after the flag has been stripped off */
+ if (p>=text_ptr) confusion("find_first_ident");
+ for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+ switch (*j/id_flag) {
+ case 2: /* |res_flag| */
+ if (name_dir[r].ilk==case_like) return case_found;
+ if (name_dir[r].ilk==operator_like) return operator_found;
+ if (name_dir[r].ilk!=raw_int) break;
+ case 1: return j;
+ case 4: case 5: /* |tok_flag| or |inner_tok_flag| */
+ if ((q=find_first_ident(tok_start+r))!=no_ident_found)
+ return q;
+ default: ; /* char, |section_flag|, fall thru: move on to next token */
+ if (*j==inserted) return no_ident_found; /* ignore inserts */
+ else if (*j==qualifier) j++; /* bypass namespace qualifier */
+ }
+ }
+ return no_ident_found;
+}
+
+@ The scraps currently being parsed must be inspected for any
+occurrence of the identifier that we're making reserved; hence
+the |for| loop below.
+
+@c
+void
+make_reserved(p) /* make the first identifier in |p->trans| like |int| */
+scrap_pointer p;
+{
+ sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
+ token_pointer tok_loc; /* pointer to |tok_value| */
+ if ((tok_loc=find_first_ident(p->trans))<=operator_found)
+ return; /* this should not happen */
+ tok_value=*tok_loc;
+ for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
+ if (p->cat==exp) {
+ if (**(p->trans)==tok_value) {
+ p->cat=raw_int;
+ **(p->trans)=tok_value%id_flag+res_flag;
+ }
+ }
+ }
+ (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=raw_int;
+ *tok_loc=tok_value%id_flag+res_flag;
+}
+
+@ In the following situations we want to mark the occurrence of
+an identifier as a definition: when |make_reserved| is just about to be
+used; after a specifier, as in |char **argv|;
+before a colon, as in \\{found}:; and in the declaration of a function,
+as in \\{main}()$\{\ldots;\}$. This is accomplished by the invocation
+of |make_underlined| at appropriate times. Notice that, in the declaration
+of a function, we find out that the identifier is being defined only after
+it has been swallowed up by an |exp|.
+
+@c
+void
+make_underlined(p)
+/* underline the entry for the first identifier in |p->trans| */
+scrap_pointer p;
+{
+ token_pointer tok_loc; /* where the first identifier appears */
+ if ((tok_loc=find_first_ident(p->trans))<=operator_found)
+ return; /* this happens, for example, in |case found:| */
+ xref_switch=def_flag;
+ underline_xref(*tok_loc%id_flag+name_dir);
+}
+
+@ We cannot use |new_xref| to underline a cross-reference at this point
+because this would just make a new cross-reference at the end of the list.
+We actually have to search through the list for the existing
+cross-reference.
+
+@<Predecl...@>=
+void underline_xref();
+
+@ @c
+void
+underline_xref(p)
+name_pointer p;
+{
+ xref_pointer q=(xref_pointer)p->xref; /* pointer to cross-reference being examined */
+ xref_pointer r; /* temporary pointer for permuting cross-references */
+ sixteen_bits m; /* cross-reference value to be installed */
+ sixteen_bits n; /* cross-reference value being examined */
+ if (no_xref) return;
+ m=section_count+xref_switch;
+ while (q != xmem) {
+ n=q->num;
+ if (n==m) return;
+ else if (m==n+def_flag) {
+ q->num=m; return;
+ }
+ else if (n>=def_flag && n<m) break;
+ q=q->xlink;
+ }
+ @<Insert new cross-reference at |q|, not at beginning of list@>;
+}
+
+@ We get to this section only when the identifier is one letter long,
+so it didn't get a non-underlined entry during phase one. But it may
+have got some explicitly underlined entries in later sections, so in order
+to preserve the numerical order of the entries in the index, we have
+to insert the new cross-reference not at the beginning of the list
+(namely, at |p->xref|), but rather right before |q|.
+
+@<Insert new cross-reference at |q|...@>=
+ append_xref(0); /* this number doesn't matter */
+ xref_ptr->xlink=(xref_pointer)p->xref; r=xref_ptr;
+ p->xref=(char*)xref_ptr;
+ while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
+ r->num=m; /* everything from |q| on is left undisturbed */
+
+@ Now comes the code that tries to match each production starting
+with a particular type of scrap. Whenever a match is discovered,
+the |squash| or |reduce| macro will cause the appropriate action
+to be performed, followed by |goto found|.
+
+@<Cases for |exp|@>=
+if (cat1==lbrace || cat1==int_like || cat1==decl) {
+ make_underlined(pp); big_app1(pp); big_app(indent); app(indent);
+ reduce(pp,1,fn_decl,0,1);
+}
+else if (cat1==unop) squash(pp,2,exp,-2,2);
+else if ((cat1==binop || cat1==ubinop) && cat2==exp)
+ squash(pp,3,exp,-2,3);
+else if (cat1==comma && cat2==exp) {
+ big_app2(pp);
+ app(opt); app('9'); big_app1(pp+2); reduce(pp,3,exp,-2,4);
+}
+else if (cat1==lpar && cat2==rpar && cat3==colon) squash(pp+3,1,base,0,5);
+else if (cat1==cast && cat2==colon) squash(pp+2,1,base,0,5);
+else if (cat1==semi) squash(pp,2,stmt,-1,6);
+else if (cat1==colon) {
+ make_underlined (pp); squash(pp,2,tag,-1,7);
+}
+else if (cat1==rbrace) squash(pp,1,stmt,-1,8);
+else if (cat1==lpar && cat2==rpar && (cat3==const_like || cat3==case_like)) {
+ big_app1(pp+2); big_app(' '); big_app1(pp+3); reduce(pp+2,2,rpar,0,9);
+}
+else if (cat1==cast && (cat2==const_like || cat2==case_like)) {
+ big_app1(pp+1); big_app(' '); big_app1(pp+2); reduce(pp+1,2,cast,0,9);
+}
+else if (cat1==exp || cat1==cast) squash(pp,2,exp,-2,10);
+
+@ @<Cases for |lpar|@>=
+if ((cat1==exp||cat1==ubinop) && cat2==rpar) squash(pp,3,exp,-2,11);
+else if (cat1==rpar) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,exp,-2,12);
+}
+else if ((cat1==decl_head || cat1==int_like || cat1==cast) && cat2==rpar)
+ squash(pp,3,cast,-2,13);
+else if ((cat1==decl_head || cat1==int_like || cat1==exp) && cat2==comma) {
+ big_app3(pp); app(opt); app('9'); reduce(pp,3,lpar,-1,14);
+}
+else if (cat1==stmt || cat1==decl) {
+ big_app2(pp); big_app(' '); reduce(pp,2,lpar,-1,15);
+}
+
+@ @<Cases for |unop|@>=
+if (cat1==exp || cat1==int_like) squash(pp,2,exp,-2,16);
+
+@ @<Cases for |ubinop|@>=
+if (cat1==cast && cat2==rpar) {
+ big_app('{'); big_app1(pp); big_app('}'); big_app1(pp+1);
+ reduce(pp,2,cast,-2,17);
+}
+else if (cat1==exp || cat1==int_like) {
+ big_app('{'); big_app1(pp); big_app('}'); big_app1(pp+1);
+ reduce(pp,2,cat1,-2,18);
+}
+else if (cat1==binop) {
+ big_app(math_rel); big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ big_app('}'); reduce(pp,2,binop,-1,19);
+}
+
+@ @<Cases for |binop|@>=
+if (cat1==binop) {
+ big_app(math_rel); big_app('{'); big_app1(pp); big_app('}');
+ big_app('{'); big_app1(pp+1); big_app('}');
+ big_app('}'); reduce(pp,2,binop,-1,20);
+}
+
+@ @<Cases for |cast|@>=
+if (cat1==lpar) squash(pp,2,lpar,-1,21);
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,21);
+}
+else if (cat1==semi) squash(pp,1,exp,-2,22);
+
+@ @<Cases for |sizeof_like|@>=
+if (cat1==cast) squash(pp,2,exp,-2,23);
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,24);
+}
+
+@ @<Cases for |int_like|@>=
+if (cat1==int_like|| cat1==struct_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,cat1,-2,25);
+}
+else if (cat1==exp && (cat2==raw_int||cat2==struct_like))
+ squash(pp,2,int_like,-2,26);
+else if (cat1==exp || cat1==ubinop || cat1==colon) {
+ big_app1(pp); big_app(' '); reduce(pp,1,decl_head,-1,27);
+}
+else if (cat1==semi || cat1==binop) squash(pp,1,decl_head,0,28);
+
+@ @<Cases for |public_like|@>=
+if (cat1==colon) squash(pp,2,tag,-1,29);
+else squash(pp,1,int_like,-2,30);
+
+@ @<Cases for |colcol|@>=
+if (cat1==exp||cat1==int_like) {
+ app(qualifier); squash(pp,2,cat1,-2,31);
+}@+else if (cat1==colcol) squash(pp,2,colcol,-1,32);
+
+@ @<Cases for |decl_head|@>=
+if (cat1==comma) {
+ big_app2(pp); big_app(' '); reduce(pp,2,decl_head,-1,33);
+}
+else if (cat1==ubinop) {
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,decl_head,-1,34);
+}
+else if (cat1==exp && cat2!=lpar && cat2!=exp && cat2!=cast) {
+ make_underlined(pp+1); squash(pp,2,decl_head,-1,35);
+}
+else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
+ cat3==semi || cat3==rpar))
+ squash(pp,3,decl_head,-1,36);
+else if (cat1==cast) squash(pp,2,decl_head,-1,37);
+else if (cat1==lbrace || cat1==int_like || cat1==decl) {
+ big_app1(pp); big_app(indent); app(indent); reduce(pp,1,fn_decl,0,38);
+}
+else if (cat1==semi) squash(pp,2,decl,-1,39);
+
+@ @<Cases for |decl|@>=
+if (cat1==decl) {
+ big_app1(pp); big_app(force); big_app1(pp+1);
+ reduce(pp,2,decl,-1,40);
+}
+else if (cat1==stmt || cat1==function) {
+ big_app1(pp); big_app(big_force);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,41);
+}
+
+@ @<Cases for |base|@>=
+if (cat1==int_like || cat1==exp) {
+ if (cat2==comma) {
+ big_app1(pp); big_app(' '); big_app2(pp+1);
+ app(opt); app('9'); reduce(pp,3,base,0,42);
+ }
+ else if (cat2==lbrace) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); big_app(' '); big_app1(pp+2);
+ reduce(pp,3,lbrace,-2,43);
+ }
+}
+
+@ @<Cases for |struct_like|@>=
+if (cat1==lbrace) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,struct_head,0,44);
+}
+else if (cat1==exp||cat1==int_like) {
+ if (cat2==lbrace || cat2==semi) {
+ make_underlined(pp+1); make_reserved(pp+1);
+ big_app1(pp); big_app(' '); big_app1(pp+1);
+ if (cat2==semi) reduce(pp,2,decl_head,0,45);
+ else {
+ big_app(' '); big_app1(pp+2);reduce(pp,3,struct_head,0,46);
+ }
+ }
+ else if (cat2==colon) squash(pp+2,1,base,2,47);
+ else if (cat2!=base) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,int_like,-2,48);
+ }
+}
+
+@ @<Cases for |struct_head|@>=
+if ((cat1==decl || cat1==stmt || cat1==function) && cat2==rbrace) {
+ big_app1(pp); big_app(indent); big_app(force); big_app1(pp+1);
+ big_app(outdent); big_app(force); big_app1(pp+2);
+ reduce(pp,3,int_like,-2,49);
+}
+else if (cat1==rbrace) {
+ big_app1(pp); app_str("\\,"); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,int_like,-2,50);
+}
+
+@ @<Cases for |fn_decl|@>=
+if (cat1==decl) {
+ big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,fn_decl,0,51);
+}
+else if (cat1==stmt) {
+ big_app1(pp); app(outdent); app(outdent); big_app(force);
+ big_app1(pp+1); reduce(pp,2,function,-1,52);
+}
+
+@ @<Cases for |function|@>=
+if (cat1==function || cat1==decl || cat1==stmt) {
+ big_app1(pp); big_app(big_force); big_app1(pp+1); reduce(pp,2,cat1,-1,53);
+}
+
+@ @<Cases for |lbrace|@>=
+if (cat1==rbrace) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,stmt,-1,54);
+}
+else if ((cat1==stmt||cat1==decl||cat1==function) && cat2==rbrace) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(force);
+ big_app1(pp+1); big_app(force); big_app(backup); big_app1(pp+2);
+ big_app(outdent); big_app(force); reduce(pp,3,stmt,-1,55);
+}
+else if (cat1==exp) {
+ if (cat2==rbrace) squash(pp,3,exp,-2,56);
+ else if (cat2==comma && cat3==rbrace) squash(pp,4,exp,-2,56);
+}
+
+@ @<Cases for |if_like|@>=
+if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,if_clause,0,57);
+}
+
+@ @<Cases for |else_like|@>=
+if (cat1==colon) squash(pp+1,1,base,1,58);
+else if (cat1==lbrace) squash(pp,1,else_head,0,59);
+else if (cat1==stmt) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force);
+ reduce(pp,2,stmt,-1,60);
+}
+
+@ @<Cases for |else_head|@>=
+if (cat1==stmt || cat1==exp) {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force);
+ reduce(pp,2,stmt,-1,61);
+}
+
+@ @<Cases for |if_clause|@>=
+if (cat1==lbrace) squash(pp,1,if_head,0,62);
+else if (cat1==stmt) {
+ if (cat2==else_like) {
+ big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
+ big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,63);
+ }@+else reduce(pp,3,else_like,0,64);
+ }
+ else squash(pp,1,else_like,0,65);
+}
+
+@ @<Cases for |if_head|@>=
+if (cat1==stmt || cat1==exp) {
+ if (cat2==else_like) {
+ big_app(force); big_app1(pp); big_app(break_space); app(noop);
+ big_app(cancel); big_app1(pp+1); big_app(force); big_app1(pp+2);
+ if (cat3==if_like) {
+ big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,66);
+ }@+else reduce(pp,3,else_like,0,67);
+ }
+ else squash(pp,1,else_head,0,68);
+}
+
+@ @<Cases for |do_like|@>=
+if (cat1==stmt && cat2==else_like && cat3==semi) {
+ big_app1(pp); big_app(break_space); app(noop); big_app(cancel);
+ big_app1(pp+1); big_app(cancel); app(noop); big_app(break_space);
+ big_app2(pp+2); reduce(pp,4,stmt,-1,69);
+}
+
+@ @<Cases for |case_like|@>=
+if (cat1==semi) squash(pp,2,stmt,-1,70);
+else if (cat1==colon) squash(pp,2,tag,-1,71);
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,72);
+}
+
+@ @<Cases for |catch_like|@>=
+if (cat1==cast || cat1==exp) {
+ big_app2(pp); big_app(indent); big_app(indent); reduce(pp,2,fn_decl,0,73);
+}
+
+@ @<Cases for |tag|@>=
+if (cat1==tag) {
+ big_app1(pp); big_app(break_space); big_app1(pp+1); reduce(pp,2,tag,-1,74);
+}
+else if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app(force); big_app(backup); big_app1(pp); big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,75);
+}
+
+@ The user can decide at run-time whether short statements should be
+grouped together on the same line.
+
+@d force_lines flags['f'] /* should each statement be on its own line? */
+@<Cases for |stmt|@>=
+if (cat1==stmt||cat1==decl||cat1==function) {
+ big_app1(pp);
+ if (cat1==function) big_app(big_force);
+ else if (cat1==decl) big_app(big_force);
+ else if (force_lines) big_app(force);
+ else big_app(break_space);
+ big_app1(pp+1); reduce(pp,2,cat1,-1,76);
+}
+
+@ @<Cases for |semi|@>=
+big_app(' '); big_app1(pp); reduce(pp,1,stmt,-1,77);
+
+@ @<Cases for |lproc|@>=
+if (cat1==define_like) make_underlined(pp+2);
+if (cat1==else_like || cat1==if_like ||cat1==define_like)
+ squash(pp,2,lproc,0,78);
+else if (cat1==rproc) {
+ app(inserted); big_app2(pp); reduce(pp,2,insert,-1,79);
+} else if (cat1==exp || cat1==function) {
+ if (cat2==rproc) {
+ app(inserted); big_app1(pp); big_app(' '); big_app2(pp+1);
+ reduce(pp,3,insert,-1,80);
+ }
+ else if (cat2==exp && cat3==rproc && cat1==exp) {
+ app(inserted); big_app1(pp); big_app(' '); big_app1(pp+1); app_str(" \\5");
+@.\\5@>
+ big_app2(pp+2); reduce(pp,4,insert,-1,80);
+ }
+}
+
+@ @<Cases for |section_scrap|@>=
+if (cat1==semi) {
+ big_app2(pp); big_app(force); reduce(pp,2,stmt,-2,81);
+}
+else squash(pp,1,exp,-2,82);
+
+@ @<Cases for |insert|@>=
+if (cat1)
+ squash(pp,2,cat1,0,83);
+
+@ @<Cases for |prelangle|@>=
+init_mathness=cur_mathness=yes_math;
+app('<'); reduce(pp,1,binop,-2,84);
+
+@ @<Cases for |prerangle|@>=
+init_mathness=cur_mathness=yes_math;
+app('>'); reduce(pp,1,binop,-2,85);
+
+@ @<Cases for |langle|@>=
+if (cat1==prerangle) {
+ big_app1(pp); app('\\'); app(','); big_app1(pp+1);
+@.\\,@>
+ reduce(pp,2,cast,-1,86);
+}
+else if (cat1==decl_head || cat1==int_like || cat1==exp) {
+ if (cat2==prerangle) squash(pp,3,cast,-1,87);
+ else if (cat2==comma) {
+ big_app3(pp); app(opt); app('9'); reduce(pp,3,langle,0,88);
+ }
+}
+
+@ @<Cases for |template_like|@>=
+if (cat1==exp && cat2==prelangle) squash(pp+2,1,langle,2,89);
+else if (cat1==exp || cat1==raw_int) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,cat1,-2,90);
+}@+ else squash(pp,1,raw_int,0,91);
+
+@ @<Cases for |new_like|@>=
+if (cat1==lpar && cat2==exp && cat3==rpar) squash(pp,4,new_like,0,92);
+else if (cat1==cast) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,93);
+}
+else if (cat1!=lpar) squash(pp,1,new_exp,0,94);
+
+@ @<Cases for |new_exp|@>=
+if (cat1==int_like || cat1==const_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,new_exp,0,95);
+}
+else if (cat1==struct_like && (cat2==exp || cat2==int_like)) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); big_app(' ');
+ big_app1(pp+2); reduce(pp,3,new_exp,0,96);
+}
+else if (cat1==raw_ubin) {
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,new_exp,0,97);
+}
+else if (cat1==lpar) squash(pp,1,exp,-2,98);
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); reduce(pp,1,exp,-2,98);
+}
+else if (cat1!=raw_int && cat1!=struct_like && cat1!=colcol)
+ squash(pp,1,exp,-2,99);
+
+@ @<Cases for |ftemplate|@>=
+if (cat1==prelangle) squash(pp+1,1,langle,1,100);
+else squash(pp,1,exp,-2,101);
+
+@ @<Cases for |for_like|@>=
+if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,else_like,-2,102);
+}
+
+@ @<Cases for |raw_ubin|@>=
+if (cat1==const_like) {
+ big_app2(pp); app_str("\\ "); reduce(pp,2,raw_ubin,0,103);
+@.\\\ @>
+} else squash(pp,1,ubinop,-2,104);
+
+@ @<Cases for |const_like|@>=
+squash(pp,1,int_like,-2,105);
+
+@ @<Cases for |raw_int|@>=
+if (cat1==prelangle) squash(pp+1,1,langle,1,106);
+else if (cat1==colcol) squash(pp,2,colcol,-1,107);
+else if (cat1==cast) squash(pp,2,raw_int,0,108);
+else if (cat1==lpar) squash(pp,1,exp,-2,109);
+else if (cat1!=langle) squash(pp,1,int_like,-3,110);
+
+@ @<Cases for |operator_like|@>=
+if (cat1==binop || cat1==unop || cat1==ubinop) {
+ if (cat2==binop) break;
+ big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
+ reduce(pp,2,exp,-2,111);
+}
+else if (cat1==new_like || cat1==delete_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,112);
+}
+else if (cat1==comma) squash(pp,2,exp,-2,113);
+else if (cat1!=raw_ubin) squash(pp,1,new_exp,0,114);
+
+@ @<Cases for |typedef_like|@>=
+if ((cat1==int_like || cat1==cast) && (cat2==comma || cat2==semi))
+ squash(pp+1,1,exp,-1,115);
+else if (cat1==int_like) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,typedef_like,0,116);
+}
+else if (cat1==exp && cat2!=lpar && cat2!=exp && cat2!=cast) {
+ make_underlined(pp+1); make_reserved(pp+1);
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,typedef_like,0,117);
+}
+else if (cat1==comma) {
+ big_app2(pp); big_app(' '); reduce(pp,2,typedef_like,0,118);
+}
+else if (cat1==semi) squash(pp,2,decl,-1,119);
+else if (cat1==ubinop && (cat2==ubinop || cat2==cast)) {
+ big_app('{'); big_app1(pp+1); big_app('}'); big_app1(pp+2);
+ reduce(pp+1,2,cat2,0,120);
+}
+
+@ @<Cases for |delete_like|@>=
+if (cat1==lpar && cat2==rpar) {
+ big_app2(pp); app('\\'); app(','); big_app1(pp+2);
+@.\\,@>
+ reduce(pp,3,delete_like,0,121);
+}
+else if (cat1==exp) {
+ big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,122);
+}
+
+@ @<Cases for |question|@>=
+if (cat1==exp && (cat2==colon || cat2==base)) {
+ (pp+2)->mathness=5*yes_math; /* this colon should be in math mode */
+ squash(pp,3,binop,-2,123);
+}
+
+@ Now here's the |reduce| procedure used in our code for productions.
+
+The `|freeze_text|' macro is used to give official status to a token list.
+Before saying |freeze_text|, items are appended to the current token list,
+and we know that the eventual number of this token list will be the current
+value of |text_ptr|. But no list of that number really exists as yet,
+because no ending point for the current list has been
+stored in the |tok_start| array. After saying |freeze_text|, the
+old current token list becomes legitimate, and its number is the current
+value of |text_ptr-1| since |text_ptr| has been increased. The new
+current token list is empty and ready to be appended to.
+Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten
+too large, since it is assumed that this test was done beforehand.
+
+@d freeze_text *(++text_ptr)=tok_ptr
+
+@c
+void
+reduce(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+{
+ scrap_pointer i, i1; /* pointers into scrap memory */
+ j->cat=c; j->trans=text_ptr;
+ j->mathness=4*cur_mathness+init_mathness;
+ freeze_text;
+ if (k>1) {
+ for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) {
+ i1->cat=i->cat; i1->trans=i->trans;
+ i1->mathness=i->mathness;
+ }
+ lo_ptr=lo_ptr-k+1;
+ }
+ pp=(pp+d<scrap_base? scrap_base: pp+d);
+ @<Print a snapshot of the scrap list if debugging @>;
+ pp--; /* we next say |pp++| */
+}
+
+@ Here's the |squash| procedure, which
+takes advantage of the simplification that occurs when |k==1|.
+
+@c
+void
+squash(j,k,c,d,n)
+scrap_pointer j;
+eight_bits c;
+short k, d, n;
+{
+ scrap_pointer i; /* pointers into scrap memory */
+ if (k==1) {
+ j->cat=c; pp=(pp+d<scrap_base? scrap_base: pp+d);
+ @<Print a snapshot...@>;
+ pp--; /* we next say |pp++| */
+ return;
+ }
+ for (i=j; i<j+k; i++) big_app1(i);
+ reduce(j,k,c,d,n);
+}
+
+@ And here now is the code that applies productions as long as possible.
+Before applying the production mechanism, we must make sure
+it has good input (at least four scraps, the length of the lhs of the
+longest rules), and that there is enough room in the memory arrays
+to hold the appended tokens and texts. Here we use a very
+conservative test; it's more important to make sure the program
+will still work if we change the production rules (within reason)
+than to squeeze the last bit of space from the memory arrays.
+
+@d safe_tok_incr 20
+@d safe_text_incr 10
+@d safe_scrap_incr 10
+
+@<Reduce the scraps using the productions until no more rules apply@>=
+while (1) {
+ @<Make sure the entries |pp| through |pp+3| of |cat| are defined@>;
+ if (tok_ptr+safe_tok_incr>tok_mem_end) {
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ overflow("token");
+ }
+ if (text_ptr+safe_text_incr>tok_start_end) {
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ overflow("text");
+ }
+ if (pp>lo_ptr) break;
+ init_mathness=cur_mathness=maybe_math;
+ @<Match a production...@>;
+}
+
+@ If we get to the end of the scrap list, category codes equal to zero are
+stored, since zero does not match anything in a production.
+
+@<Make sure the entries...@>=
+if (lo_ptr<pp+3) {
+ while (hi_ptr<=scrap_ptr && lo_ptr!=pp+3) {
+ (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness;
+ lo_ptr->trans=(hi_ptr++)->trans;
+ }
+ for (i=lo_ptr+1;i<=pp+3;i++) i->cat=0;
+}
+
+@ If \.{CWEAVE} is being run in debugging mode, the production numbers and
+current stack categories will be printed out when |tracing| is set to 2;
+a sequence of two or more irreducible scraps will be printed out when
+|tracing| is set to 1.
+
+@<Global...@>=
+int tracing; /* can be used to show parsing details */
+
+@ @<Print a snapsh...@>=
+{ scrap_pointer k; /* pointer into |scrap_info| */
+ if (tracing==2) {
+ printf("\n%d:",n);
+ for (k=scrap_base; k<=lo_ptr; k++) {
+ if (k==pp) putxchar('*'); else putxchar(' ');
+ if (k->mathness %4 == yes_math) putchar('+');
+ else if (k->mathness %4 == no_math) putchar('-');
+ print_cat(k->cat);
+ if (k->mathness /4 == yes_math) putchar('+');
+ else if (k->mathness /4 == no_math) putchar('-');
+ }
+ if (hi_ptr<=scrap_ptr) printf("..."); /* indicate that more is coming */
+ }
+}
+
+@ The |translate| function assumes that scraps have been stored in
+positions |scrap_base| through |scrap_ptr| of |cat| and |trans|. It
+applies productions as much as
+possible. The result is a token list containing the translation of
+the given sequence of scraps.
+
+After calling |translate|, we will have |text_ptr+3<=max_texts| and
+|tok_ptr+6<=max_toks|, so it will be possible to create up to three token
+lists with up to six tokens without checking for overflow. Before calling
+|translate|, we should have |text_ptr<max_texts| and |scrap_ptr<max_scraps|,
+since |translate| might add a new text and a new scrap before it checks
+for overflow.
+
+@c
+text_pointer
+translate() /* converts a sequence of scraps */
+{
+ scrap_pointer i, /* index into |cat| */
+ j; /* runs through final scraps */
+ pp=scrap_base; lo_ptr=pp-1; hi_ptr=pp;
+ @<If tracing, print an indication of where we are@>;
+ @<Reduce the scraps...@>;
+ @<Combine the irreducible scraps that remain@>;
+}
+
+@ If the initial sequence of scraps does not reduce to a single scrap,
+we concatenate the translations of all remaining scraps, separated by
+blank spaces, with dollar signs surrounding the translations of scraps
+where appropriate.
+
+@<Combine the irreducible...@>= {
+ @<If semi-tracing, show the irreducible scraps@>;
+ for (j=scrap_base; j<=lo_ptr; j++) {
+ if (j!=scrap_base) app(' ');
+ if (j->mathness % 4 == yes_math) app('$');
+ app1(j);
+ if (j->mathness / 4 == yes_math) app('$');
+ if (tok_ptr+6>tok_mem_end) overflow("token");
+ }
+ freeze_text; return(text_ptr-1);
+}
+
+@ @<If semi-tracing, show the irreducible scraps@>=
+if (lo_ptr>scrap_base && tracing==1) {
+ printf("\nIrreducible scrap sequence in section %d:",section_count);
+@.Irreducible scrap sequence...@>
+ mark_harmless;
+ for (j=scrap_base; j<=lo_ptr; j++) {
+ printf(" "); print_cat(j->cat);
+ }
+}
+
+@ @<If tracing,...@>=
+if (tracing==2) {
+ printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
+@.Tracing after...@>
+ if (loc>buffer+50) {
+ printf("...");
+ term_write(loc-51,51);
+ }
+ else term_write(buffer,loc-buffer);
+}
+
+@* Initializing the scraps.
+If we are going to use the powerful production mechanism just developed, we
+must get the scraps set up in the first place, given a \CEE/ text. A table
+of the initial scraps corresponding to \CEE/ tokens appeared above in the
+section on parsing; our goal now is to implement that table. We shall do this
+by implementing a subroutine called |C_parse| that is analogous to the
+|C_xref| routine used during phase one.
+
+Like |C_xref|, the |C_parse| procedure starts with the current
+value of |next_control| and it uses the operation |next_control=get_next()|
+repeatedly to read \CEE/ text until encountering the next `\.{\v}' or
+`\.{/*}', or until |next_control>=format_code|. The scraps corresponding to
+what it reads are appended into the |cat| and |trans| arrays, and |scrap_ptr|
+is advanced.
+
+@c
+void
+C_parse(spec_ctrl) /* creates scraps from \CEE/ tokens */
+ eight_bits spec_ctrl;
+{
+ int count; /* characters remaining before string break */
+ while (next_control<format_code || next_control==spec_ctrl) {
+ @<Append the scrap appropriate to |next_control|@>;
+ next_control=get_next();
+ if (next_control=='|' || next_control==begin_comment ||
+ next_control==begin_short_comment) return;
+ }
+}
+
+@ The following macro is used to append a scrap whose tokens have just
+been appended:
+
+@d app_scrap(c,b) {
+ (++scrap_ptr)->cat=(c); scrap_ptr->trans=text_ptr;
+ scrap_ptr->mathness=5*(b); /* no no, yes yes, or maybe maybe */
+ freeze_text;
+}
+
+@ @<Append the scr...@>=
+@<Make sure that there is room for the new scraps, tokens, and texts@>;
+switch (next_control) {
+ case section_name:
+ app(section_flag+(int)(cur_section-name_dir));
+ app_scrap(section_scrap,maybe_math);
+ app_scrap(exp,yes_math);@+break;
+ case string: case constant: case verbatim: @<Append a string or constant@>;
+ @+break;
+ case identifier: app_cur_id(1);@+break;
+ case TeX_string: @<Append a \TEX/ string, without forming a scrap@>;@+break;
+ case '/': case '.':
+ app(next_control); app_scrap(binop,yes_math);@+break;
+ case '<': app_str("\\langle");@+app_scrap(prelangle,yes_math);@+break;
+@.\\langle@>
+ case '>': app_str("\\rangle");@+app_scrap(prerangle,yes_math);@+break;
+@.\\rangle@>
+ case '=': app_str("\\K"); app_scrap(binop,yes_math);@+break;
+@.\\K@>
+ case '|': app_str("\\OR"); app_scrap(binop,yes_math);@+break;
+@.\\OR@>
+ case '^': app_str("\\XOR"); app_scrap(binop,yes_math);@+break;
+@.\\XOR@>
+ case '%': app_str("\\MOD"); app_scrap(binop,yes_math);@+break;
+@.\\MOD@>
+ case '!': app_str("\\R"); app_scrap(unop,yes_math);@+break;
+@.\\R@>
+ case '~': app_str("\\CM"); app_scrap(unop,yes_math);@+break;
+@.\\CM@>
+ case '+': case '-': app(next_control); app_scrap(ubinop,yes_math);@+break;
+ case '*': app(next_control); app_scrap(raw_ubin,yes_math);@+break;
+ case '&': app_str("\\AND"); app_scrap(raw_ubin,yes_math);@+break;
+@.\\AND@>
+ case '?': app_str("\\?"); app_scrap(question,yes_math);@+break;
+@.\\?@>
+ case '#': app_str("\\#"); app_scrap(ubinop,yes_math);@+break;
+@.\\\#@>
+ case ignore: case xref_roman: case xref_wildcard:
+ case xref_typewriter: case noop:@+break;
+ case '(': case '[': app(next_control); app_scrap(lpar,maybe_math);@+break;
+ case ')': case ']': app(next_control); app_scrap(rpar,maybe_math);@+break;
+ case '{': app_str("\\{"@q}@>); app_scrap(lbrace,yes_math);@+break;
+@.\\\{@>@q}@>
+ case '}': app_str(@q{@>"\\}"); app_scrap(rbrace,yes_math);@+break;
+@q{@>@.\\\}@>
+ case ',': app(','); app_scrap(comma,yes_math);@+break;
+ case ';': app(';'); app_scrap(semi,maybe_math);@+break;
+ case ':': app(':'); app_scrap(colon,no_math);@+break;@/
+ @t\4@> @<Cases involving nonstandard characters@>@;
+ case thin_space: app_str("\\,"); app_scrap(insert,maybe_math);@+break;
+@.\\,@>
+ case math_break: app(opt); app_str("0");
+ app_scrap(insert,maybe_math);@+break;
+ case line_break: app(force); app_scrap(insert,no_math);@+break;
+ case left_preproc: app(force); app(preproc_line);
+ app_str("\\#"); app_scrap(lproc,no_math);@+break;
+@.\\\#@>
+ case right_preproc: app(force); app_scrap(rproc,no_math);@+break;
+ case big_line_break: app(big_force); app_scrap(insert,no_math);@+break;
+ case no_line_break: app(big_cancel); app(noop); app(break_space);
+ app(noop); app(big_cancel);
+ app_scrap(insert,no_math);@+break;
+ case pseudo_semi: app_scrap(semi,maybe_math);@+break;
+ case macro_arg_open: app_scrap(begin_arg,maybe_math);@+break;
+ case macro_arg_close: app_scrap(end_arg,maybe_math);@+break;
+ case join: app_str("\\J"); app_scrap(insert,no_math);@+break;
+@.\\J@>
+ case output_defs_code: app(force); app_str("\\ATH"); app(force);
+ app_scrap(insert,no_math);@+break;
+@.\\ATH@>
+ default: app(inserted); app(next_control);
+ app_scrap(insert,maybe_math);@+break;
+}
+
+@ @<Make sure that there is room for the new...@>=
+if (scrap_ptr+safe_scrap_incr>scrap_info_end ||
+ tok_ptr+safe_tok_incr>tok_mem_end @| ||
+ text_ptr+safe_text_incr>tok_start_end) {
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ overflow("scrap/token/text");
+}
+
+@ Some nonstandard characters may have entered \.{CWEAVE} by means of
+standard ones. They are converted to \TEX/ control sequences so that it is
+possible to keep \.{CWEAVE} from outputting unusual |char| codes.
+
+@<Cases involving nonstandard...@>=
+case not_eq: app_str("\\I");@+app_scrap(binop,yes_math);@+break;
+@.\\I@>
+case lt_eq: app_str("\\Z");@+app_scrap(binop,yes_math);@+break;
+@.\\Z@>
+case gt_eq: app_str("\\G");@+app_scrap(binop,yes_math);@+break;
+@.\\G@>
+case eq_eq: app_str("\\E");@+app_scrap(binop,yes_math);@+break;
+@.\\E@>
+case and_and: app_str("\\W");@+app_scrap(binop,yes_math);@+break;
+@.\\W@>
+case or_or: app_str("\\V");@+app_scrap(binop,yes_math);@+break;
+@.\\V@>
+case plus_plus: app_str("\\PP");@+app_scrap(unop,yes_math);@+break;
+@.\\PP@>
+case minus_minus: app_str("\\MM");@+app_scrap(unop,yes_math);@+break;
+@.\\MM@>
+case minus_gt: app_str("\\MG");@+app_scrap(binop,yes_math);@+break;
+@.\\MG@>
+case gt_gt: app_str("\\GG");@+app_scrap(binop,yes_math);@+break;
+@.\\GG@>
+case lt_lt: app_str("\\LL");@+app_scrap(binop,yes_math);@+break;
+@.\\LL@>
+case dot_dot_dot: app_str("\\,\\ldots\\,");@+app_scrap(raw_int,yes_math);
+ @+break;
+@.\\,@>
+@.\\ldots@>
+case colon_colon: app_str("\\DC");@+app_scrap(colcol,maybe_math);@+break;
+@.\\DC@>
+case period_ast: app_str("\\PA");@+app_scrap(binop,yes_math);@+break;
+@.\\PA@>
+case minus_gt_ast: app_str("\\MGA");@+app_scrap(binop,yes_math);@+break;
+@.\\MGA@>
+
+@ The following code must use |app_tok| instead of |app| in order to
+protect against overflow. Note that |tok_ptr+1<=max_toks| after |app_tok|
+has been used, so another |app| is legitimate before testing again.
+
+Many of the special characters in a string must be prefixed by `\.\\' so that
+\TEX/ will print them properly.
+@^special string characters@>
+
+@<Append a string or...@>=
+count= -1;
+if (next_control==constant) app_str("\\T{"@q}@>);
+@.\\T@>
+else if (next_control==string) {
+ count=20; app_str("\\.{"@q}@>);
+}
+@.\\.@>
+else app_str("\\vb{"@q}@>);
+@.\\vb@>
+while (id_first<id_loc) {
+ if (count==0) { /* insert a discretionary break in a long string */
+ app_str(@q(@>@q{@>"}\\)\\.{"@q}@>); count=20;
+@q(@>@.\\)@>
+ }
+@^high-bit character handling@>
+ if((eight_bits)(*id_first)>0177) {
+ app_tok(quoted_char);
+ app_tok((eight_bits)(*id_first++));
+ }
+ else {
+ switch (*id_first) {
+ case ' ':case '\\':case '#':case '%':case '$':case '^':
+ case '{': case '}': case '~': case '&': case '_': app('\\'); break;
+@.\\\ @>
+@.\\\\@>
+@.\\\#@>
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@.\\\{@>@q}@>
+@q{@>@.\\\}@>
+@.\\\~@>
+@.\\\&@>
+@.\\\_@>
+ case '@@': if (*(id_first+1)=='@@') id_first++;
+ else err_print("! Double @@ should be used in strings");
+@.Double @@ should be used...@>
+ }
+ app_tok(*id_first++);
+ }
+ count--;
+}
+app(@q{@>'}');
+app_scrap(exp,maybe_math);
+
+@ We do not make the \TEX/ string into a scrap, because there is no
+telling what the user will be putting into it; instead we leave it
+open, to be picked up by the next scrap. If it comes at the end of a
+section, it will be made into a scrap when |finish_C| is called.
+
+There's a known bug here, in cases where an adjacent scrap is
+|prelangle| or |prerangle|. Then the \TEX/ string can disappear
+when the \.{\\langle} or \.{\\rangle} becomes \.{<} or \.{>}.
+For example, if the user writes \.{\v x<@@ty@@>\v}, the \TEX/ string
+\.{\\hbox\{y\}} eventually becomes part of an |insert| scrap, which is combined
+with a |prelangle| scrap and eventually lost. The best way to work around
+this bug is probably to enclose the \.{@@t...@@>} in \.{@@[...@@]} so that
+the \TEX/ string is treated as an expression.
+@^bug, known@>
+
+@<Append a \TEX/ string, without forming a scrap@>=
+app_str("\\hbox{"@q}@>);
+@^high-bit character handling@>
+while (id_first<id_loc)
+ if((eight_bits)(*id_first)>0177) {
+ app_tok(quoted_char);
+ app_tok((eight_bits)(*id_first++));
+ }
+ else {
+ if (*id_first=='@@') id_first++;
+ app_tok(*id_first++);
+ }
+app(@q{@>'}');
+
+@ The function |app_cur_id| appends the current identifier to the
+token list; it also builds a new scrap if |scrapping==1|.
+
+@<Predec...@>=
+void app_cur_id();
+
+@ @c
+void
+app_cur_id(scrapping)
+boolean scrapping; /* are we making this into a scrap? */
+{
+ name_pointer p=id_lookup(id_first,id_loc,normal);
+ if (p->ilk<=custom) { /* not a reserved word */
+ app(id_flag+(int)(p-name_dir));
+ if (scrapping) app_scrap(p->ilk==func_template? ftemplate: exp,
+ p->ilk==custom? yes_math: maybe_math);
+@.\\NULL@>
+ } else {
+ app(res_flag+(int)(p-name_dir));
+ if (scrapping) {
+ if (p->ilk==alfop) app_scrap(ubinop,yes_math)@;
+ else app_scrap(p->ilk,maybe_math);
+ }
+ }
+}
+
+@ When the `\.{\v}' that introduces \CEE/ text is sensed, a call on
+|C_translate| will return a pointer to the \TEX/ translation of
+that text. If scraps exist in |scrap_info|, they are
+unaffected by this translation process.
+
+@c
+text_pointer
+C_translate()
+{
+ text_pointer p; /* points to the translation */
+ scrap_pointer save_base; /* holds original value of |scrap_base| */
+ save_base=scrap_base; scrap_base=scrap_ptr+1;
+ C_parse(section_name); /* get the scraps together */
+ if (next_control!='|') err_print("! Missing '|' after C text");
+@.Missing '|'...@>
+ app_tok(cancel); app_scrap(insert,maybe_math);
+ /* place a |cancel| token as a final ``comment'' */
+ p=translate(); /* make the translation */
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ scrap_ptr=scrap_base-1; scrap_base=save_base; /* scrap the scraps */
+ return(p);
+}
+
+@ The |outer_parse| routine is to |C_parse| as |outer_xref|
+is to |C_xref|: It constructs a sequence of scraps for \CEE/ text
+until |next_control>=format_code|. Thus, it takes care of embedded comments.
+
+The token list created from within `\pb' brackets is output as an argument
+to \.{\\PB}, if the user has invoked \.{CWEAVE} with the \.{+e} flag.
+Although \.{cwebmac} ignores \.{\\PB}, other macro packages
+might use it to localize the special meaning of the macros that mark up
+program text.
+
+@d make_pb flags['e']
+
+@c
+void
+outer_parse() /* makes scraps from \CEE/ tokens and comments */
+{
+ int bal; /* brace level in comment */
+ text_pointer p, q; /* partial comments */
+ while (next_control<format_code)
+ if (next_control!=begin_comment && next_control!=begin_short_comment)
+ C_parse(ignore);
+ else {
+ boolean is_long_comment=(next_control==begin_comment);
+ @<Make sure that there is room for the new...@>;
+ app(cancel); app(inserted);
+ if (is_long_comment) app_str("\\C{"@q}@>);
+@.\\C@>
+ else app_str("\\SHC{"@q}@>);
+@.\\SHC@>
+ bal=copy_comment(is_long_comment,1); next_control=ignore;
+ while (bal>0) {
+ p=text_ptr; freeze_text; q=C_translate();
+ /* at this point we have |tok_ptr+6<=max_toks| */
+ app(tok_flag+(int)(p-tok_start));
+ if (make_pb) app_str("\\PB{");
+@.\\PB@>
+ app(inner_tok_flag+(int)(q-tok_start));
+ if (make_pb) app_tok('}');
+ if (next_control=='|') {
+ bal=copy_comment(is_long_comment,bal);
+ next_control=ignore;
+ }
+ else bal=0; /* an error has been reported */
+ }
+ app(force); app_scrap(insert,no_math);
+ /* the full comment becomes a scrap */
+ }
+}
+
+@* Output of tokens.
+So far our programs have only built up multi-layered token lists in
+\.{CWEAVE}'s internal memory; we have to figure out how to get them into
+the desired final form. The job of converting token lists to characters in
+the \TEX/ output file is not difficult, although it is an implicitly
+recursive process. Four main considerations had to be kept in mind when
+this part of \.{CWEAVE} was designed. (a) There are two modes of output:
+|outer| mode, which translates tokens like |force| into line-breaking
+control sequences, and |inner| mode, which ignores them except that blank
+spaces take the place of line breaks. (b) The |cancel| instruction applies
+to adjacent token or tokens that are output, and this cuts across levels
+of recursion since `|cancel|' occurs at the beginning or end of a token
+list on one level. (c) The \TEX/ output file will be semi-readable if line
+breaks are inserted after the result of tokens like |break_space| and
+|force|. (d) The final line break should be suppressed, and there should
+be no |force| token output immediately after `\.{\\Y\\B}'.
+
+@ The output process uses a stack to keep track of what is going on at
+different ``levels'' as the token lists are being written out. Entries on
+this stack have three parts:
+
+\yskip\hang |end_field| is the |tok_mem| location where the token list of a
+particular level will end;
+
+\yskip\hang |tok_field| is the |tok_mem| location from which the next token
+on a particular level will be read;
+
+\yskip\hang |mode_field| is the current mode, either |inner| or |outer|.
+
+\yskip\noindent The current values of these quantities are referred to
+quite frequently, so they are stored in a separate place instead of in the
+|stack| array. We call the current values |cur_end|, |cur_tok|, and
+|cur_mode|.
+
+The global variable |stack_ptr| tells how many levels of output are
+currently in progress. The end of output occurs when an |end_translation|
+token is found, so the stack is never empty except when we first begin the
+output process.
+
+@d inner 0 /* value of |mode| for \CEE/ texts within \TEX/ texts */
+@d outer 1 /* value of |mode| for \CEE/ texts in sections */
+
+@<Typed...@>= typedef int mode;
+typedef struct {
+ token_pointer end_field; /* ending location of token list */
+ token_pointer tok_field; /* present location within token list */
+ boolean mode_field; /* interpretation of control tokens */
+} output_state;
+typedef output_state *stack_pointer;
+
+@ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */
+@d cur_tok cur_state.tok_field /* location of next output token in |tok_mem| */
+@d cur_mode cur_state.mode_field /* current mode of interpretation */
+@d init_stack stack_ptr=stack;cur_mode=outer /* initialize the stack */
+
+@<Global...@>=
+output_state cur_state; /* |cur_end|, |cur_tok|, |cur_mode| */
+output_state stack[stack_size]; /* info for non-current levels */
+stack_pointer stack_ptr; /* first unused location in the output state stack */
+stack_pointer stack_end=stack+stack_size-1; /* end of |stack| */
+stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */
+
+@ @<Set init...@>=
+max_stack_ptr=stack;
+
+@ To insert token-list |p| into the output, the |push_level| subroutine
+is called; it saves the old level of output and gets a new one going.
+The value of |cur_mode| is not changed.
+
+@c
+void
+push_level(p) /* suspends the current level */
+text_pointer p;
+{
+ if (stack_ptr==stack_end) overflow("stack");
+ if (stack_ptr>stack) { /* save current state */
+ stack_ptr->end_field=cur_end;
+ stack_ptr->tok_field=cur_tok;
+ stack_ptr->mode_field=cur_mode;
+ }
+ stack_ptr++;
+ if (stack_ptr>max_stack_ptr) max_stack_ptr=stack_ptr;
+ cur_tok=*p; cur_end=*(p+1);
+}
+
+@ Conversely, the |pop_level| routine restores the conditions that were in
+force when the current level was begun. This subroutine will never be
+called when |stack_ptr==1|.
+
+@c
+void
+pop_level()
+{
+ cur_end=(--stack_ptr)->end_field;
+ cur_tok=stack_ptr->tok_field; cur_mode=stack_ptr->mode_field;
+}
+
+@ The |get_output| function returns the next byte of output that is not a
+reference to a token list. It returns the values |identifier| or |res_word|
+or |section_code| if the next token is to be an identifier (typeset in
+italics), a reserved word (typeset in boldface), or a section name (typeset
+by a complex routine that might generate additional levels of output).
+In these cases |cur_name| points to the identifier or section name in
+question.
+
+@<Global...@>=
+name_pointer cur_name;
+
+@ @d res_word 0201 /* returned by |get_output| for reserved words */
+@d section_code 0200 /* returned by |get_output| for section names */
+
+@c
+eight_bits
+get_output() /* returns the next token of output */
+{
+ sixteen_bits a; /* current item read from |tok_mem| */
+ restart: while (cur_tok==cur_end) pop_level();
+ a=*(cur_tok++);
+ if (a>=0400) {
+ cur_name=a % id_flag + name_dir;
+ switch (a / id_flag) {
+ case 2: return(res_word); /* |a==res_flag+cur_name| */
+ case 3: return(section_code); /* |a==section_flag+cur_name| */
+ case 4: push_level(a % id_flag + tok_start); goto restart;
+ /* |a==tok_flag+cur_name| */
+ case 5: push_level(a % id_flag + tok_start); cur_mode=inner; goto restart;
+ /* |a==inner_tok_flag+cur_name| */
+ default: return(identifier); /* |a==id_flag+cur_name| */
+ }
+ }
+ return(a);
+}
+
+@ The real work associated with token output is done by |make_output|.
+This procedure appends an |end_translation| token to the current token list,
+and then it repeatedly calls |get_output| and feeds characters to the output
+buffer until reaching the |end_translation| sentinel. It is possible for
+|make_output| to be called recursively, since a section name may include
+embedded \CEE/ text; however, the depth of recursion never exceeds one
+level, since section names cannot be inside of section names.
+
+A procedure called |output_C| does the scanning, translation, and
+output of \CEE/ text within `\pb' brackets, and this procedure uses
+|make_output| to output the current token list. Thus, the recursive call
+of |make_output| actually occurs when |make_output| calls |output_C|
+while outputting the name of a section.
+@^recursion@>
+
+@c
+void
+output_C() /* outputs the current token list */
+{
+ token_pointer save_tok_ptr;
+ text_pointer save_text_ptr;
+ sixteen_bits save_next_control; /* values to be restored */
+ text_pointer p; /* translation of the \CEE/ text */
+ save_tok_ptr=tok_ptr; save_text_ptr=text_ptr;
+ save_next_control=next_control; next_control=ignore; p=C_translate();
+ app(inner_tok_flag+(int)(p-tok_start));
+ if (make_pb) {
+ out_str("\\PB{"); make_output(); out('}');
+@.\\PB@>
+ }@+else make_output(); /* output the list */
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ text_ptr=save_text_ptr; tok_ptr=save_tok_ptr; /* forget the tokens */
+ next_control=save_next_control; /* restore |next_control| to original state */
+}
+
+@ Here is \.{CWEAVE}'s major output handler.
+
+@<Predecl...@>=
+void make_output();
+
+@ @c
+void
+make_output() /* outputs the equivalents of tokens */
+{
+ eight_bits a, /* current output byte */
+ b; /* next output byte */
+ int c; /* count of |indent| and |outdent| tokens */
+ char scratch[longest_name]; /* scratch area for section names */
+ char *k, *k_limit; /* indices into |scratch| */
+ char *j; /* index into |buffer| */
+ char *p; /* index into |byte_mem| */
+ char delim; /* first and last character of string being copied */
+ char *save_loc, *save_limit; /* |loc| and |limit| to be restored */
+ name_pointer cur_section_name; /* name of section being output */
+ boolean save_mode; /* value of |cur_mode| before a sequence of breaks */
+ app(end_translation); /* append a sentinel */
+ freeze_text; push_level(text_ptr-1);
+ while (1) {
+ a=get_output();
+ reswitch: switch(a) {
+ case end_translation: return;
+ case identifier: case res_word: @<Output an identifier@>; break;
+ case section_code: @<Output a section name@>; break;
+ case math_rel: out_str("\\MRL{"@q}@>);
+@.\\MRL@>
+ case noop: case inserted: break;
+ case cancel: case big_cancel: c=0; b=a;
+ while (1) {
+ a=get_output();
+ if (a==inserted) continue;
+ if ((a<indent && !(b==big_cancel&&a==' ')) || a>big_force) break;
+ if (a==indent) c++; else if (a==outdent) c--;
+ else if (a==opt) a=get_output();
+ }
+ @<Output saved |indent| or |outdent| tokens@>;
+ goto reswitch;
+ case indent: case outdent: case opt: case backup: case break_space:
+ case force: case big_force: case preproc_line: @<Output a control,
+ look ahead in case of line breaks, possibly |goto reswitch|@>; break;
+ case quoted_char: out(*(cur_tok++));
+ case qualifier: break;
+ default: out(a); /* otherwise |a| is an ordinary character */
+ }
+ }
+}
+
+@ An identifier of length one does not have to be enclosed in braces, and it
+looks slightly better if set in a math-italic font instead of a (slightly
+narrower) text-italic font. Thus we output `\.{\\\v}\.{a}' but
+`\.{\\\\\{aa\}}'.
+
+@<Output an identifier@>=
+out('\\');
+if (a==identifier) {
+ if (cur_name->ilk==custom && !doing_format) {
+ custom_out:
+ for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+ out(*p=='_'? 'x': *p=='$'? 'X': *p);
+ break;
+ } else if (is_tiny(cur_name)) out('|')@;
+@.\\|@>
+ else { delim='.';
+ for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++)
+ if (xislower(*p)) { /* not entirely uppercase */
+ delim='\\'; break;
+ }
+ out(delim);
+ }
+@.\\\\@>
+@.\\.@>
+}@+else if (cur_name->ilk==alfop) {
+ out('X');
+ goto custom_out;
+}@+else out('&'); /* |a==res_word| */
+@.\\\&@>
+if (is_tiny(cur_name)) {
+ if (isxalpha((cur_name->byte_start)[0]))
+ out('\\');
+ out((cur_name->byte_start)[0]);
+}
+else out_name(cur_name,1);
+
+@ The current mode does not affect the behavior of \.{CWEAVE}'s output routine
+except when we are outputting control tokens.
+
+@<Output a control...@>=
+if (a<break_space || a==preproc_line) {
+ if (cur_mode==outer) {
+ out('\\'); out(a-cancel+'0');
+@.\\1@>
+@.\\2@>
+@.\\3@>
+@.\\4@>
+@.\\8@>
+ if (a==opt) {
+ b=get_output(); /* |opt| is followed by a digit */
+ if (b!='0' || force_lines==0) out(b)@;
+ else out_str("{-1}"); /* |force_lines| encourages more \.{@@\v} breaks */
+ }
+ } else if (a==opt) b=get_output(); /* ignore digit following |opt| */
+ }
+else @<Look ahead for strongest line break, |goto reswitch|@>
+
+@ If several of the tokens |break_space|, |force|, |big_force| occur in a
+row, possibly mixed with blank spaces (which are ignored),
+the largest one is used. A line break also occurs in the output file,
+except at the very end of the translation. The very first line break
+is suppressed (i.e., a line break that follows `\.{\\Y\\B}').
+
+@<Look ahead for st...@>= {
+ b=a; save_mode=cur_mode; c=0;
+ while (1) {
+ a=get_output();
+ if (a==inserted) continue;
+ if (a==cancel || a==big_cancel) {
+ @<Output saved |indent| or |outdent| tokens@>;
+ goto reswitch; /* |cancel| overrides everything */
+ }
+ if ((a!=' ' && a<indent) || a==backup || a>big_force) {
+ if (save_mode==outer) {
+ if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\B",4)==0)
+ goto reswitch;
+ @<Output saved |indent| or |outdent| tokens@>;
+ out('\\'); out(b-cancel+'0');
+@.\\5@>
+@.\\6@>
+@.\\7@>
+ if (a!=end_translation) finish_line();
+ }
+ else if (a!=end_translation && cur_mode==inner) out(' ');
+ goto reswitch;
+ }
+ if (a==indent) c++;
+ else if (a==outdent) c--;
+ else if (a==opt) a=get_output();
+ else if (a>b) b=a; /* if |a==' '| we have |a<b| */
+ }
+}
+
+@ @<Output saved...@>=
+ for (;c>0;c--) out_str("\\1");
+@.\\1@>
+ for (;c<0;c++) out_str("\\2");
+@.\\2@>
+
+@ The remaining part of |make_output| is somewhat more complicated. When we
+output a section name, we may need to enter the parsing and translation
+routines, since the name may contain \CEE/ code embedded in
+\pb\ constructions. This \CEE/ code is placed at the end of the active
+input buffer and the translation process uses the end of the active
+|tok_mem| area.
+
+@<Output a section name@>= {
+ out_str("\\X");
+@.\\X@>
+ cur_xref=(xref_pointer)cur_name->xref;
+ if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num>=def_flag) {
+ out_section(cur_xref->num-def_flag);
+ if (phase==3) {
+ cur_xref=cur_xref->xlink;
+ while (cur_xref->num>=def_flag) {
+ out_str(", ");
+ out_section(cur_xref->num-def_flag);
+ cur_xref=cur_xref->xlink;
+ }
+ }
+ }
+ else out('0'); /* output the section number, or zero if it was undefined */
+ out(':');
+ if (an_output) out_str("\\.{"@q}@>);
+@.\\.@>
+ @<Output the text of the section name@>;
+ if (an_output) out_str(@q{@>" }");
+ out_str("\\X");
+}
+
+@ @<Output the text...@>=
+sprint_section_name(scratch,cur_name);
+k=scratch;
+k_limit=scratch+strlen(scratch);
+cur_section_name=cur_name;
+while (k<k_limit) {
+ b=*(k++);
+ if (b=='@@') @<Skip next character, give error if not `\.{@@}'@>;
+ if (an_output)
+ switch (b) {
+ case ' ':case '\\':case '#':case '%':case '$':case '^':
+ case '{': case '}': case '~': case '&': case '_':
+ out('\\'); /* falls through */
+@.\\\ @>
+@.\\\\@>
+@.\\\#@>
+@.\\\%@>
+@.\\\$@>
+@.\\\^@>
+@.\\\{@>@q}@>
+@q{@>@.\\\}@>
+@.\\\~@>
+@.\\\&@>
+@.\\\_@>
+ default: out(b);
+ }
+ else if (b!='|') out(b)
+ else {
+ @<Copy the \CEE/ text into the |buffer| array@>;
+ save_loc=loc; save_limit=limit; loc=limit+2; limit=j+1;
+ *limit='|'; output_C();
+ loc=save_loc; limit=save_limit;
+ }
+}
+
+@ @<Skip next char...@>=
+if (*k++!='@@') {
+ printf("\n! Illegal control code in section name: <");
+@.Illegal control code...@>
+ print_section_name(cur_section_name); printf("> "); mark_error;
+}
+
+@ The \CEE/ text enclosed in \pb\ should not contain `\.{\v}' characters,
+except within strings. We put a `\.{\v}' at the front of the buffer, so that an
+error message that displays the whole buffer will look a little bit sensible.
+The variable |delim| is zero outside of strings, otherwise it
+equals the delimiter that began the string being copied.
+
+@<Copy the \CEE/ text into...@>=
+j=limit+1; *j='|'; delim=0;
+while (1) {
+ if (k>=k_limit) {
+ printf("\n! C text in section name didn't end: <");
+@.C text...didn't end@>
+ print_section_name(cur_section_name); printf("> "); mark_error; break;
+ }
+ b=*(k++);
+ if (b=='@@' || (b=='\\' && delim!=0))
+ @<Copy a quoted character into the buffer@>
+ else {
+ if (b=='\'' || b=='"')
+ if (delim==0) delim=b;
+ else if (delim==b) delim=0;
+ if (b!='|' || delim!=0) {
+ if (j>buffer+long_buf_size-3) overflow("buffer");
+ *(++j)=b;
+ }
+ else break;
+ }
+}
+
+@ @<Copy a quoted char...@>= {
+ if (j>buffer+long_buf_size-4) overflow("buffer");
+ *(++j)=b; *(++j)=*(k++);
+}
+
+@** Phase two processing.
+We have assembled enough pieces of the puzzle in order to be ready to specify
+the processing in \.{CWEAVE}'s main pass over the source file. Phase two
+is analogous to phase one, except that more work is involved because we must
+actually output the \TEX/ material instead of merely looking at the
+\.{CWEB} specifications.
+
+@<Predecl...@>=
+void phase_two();
+
+@ @c
+void
+phase_two() {
+reset_input(); if (show_progress) printf("\nWriting the output file...");
+@.Writing the output file...@>
+section_count=0; format_visible=1; copy_limbo();
+finish_line(); flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
+while (!input_has_ended) @<Translate the current section@>;
+}
+
+@ The output file will contain the control sequence \.{\\Y} between non-null
+sections of a section, e.g., between the \TEX/ and definition parts if both
+are nonempty. This puts a little white space between the parts when they are
+printed. However, we don't want \.{\\Y} to occur between two definitions
+within a single section. The variables |out_line| or |out_ptr| will
+change if a section is non-null, so the following macros `|save_position|'
+and `|emit_space_if_needed|' are able to handle the situation:
+
+@d save_position save_line=out_line; save_place=out_ptr
+@d emit_space_if_needed if (save_line!=out_line || save_place!=out_ptr)
+ out_str("\\Y");
+ space_checked=1
+@.\\Y@>
+
+@<Global...@>=
+int save_line; /* former value of |out_line| */
+char *save_place; /* former value of |out_ptr| */
+int sec_depth; /* the integer, if any, following \.{@@*} */
+boolean space_checked; /* have we done |emit_space_if_needed|? */
+boolean format_visible; /* should the next format declaration be output? */
+boolean doing_format=0; /* are we outputting a format declaration? */
+boolean group_found=0; /* has a starred section occurred? */
+
+@ @<Translate the current section@>= {
+ section_count++;
+ @<Output the code for the beginning of a new section@>;
+ save_position;
+ @<Translate the \TEX/ part of the current section@>;
+ @<Translate the definition part of the current section@>;
+ @<Translate the \CEE/ part of the current section@>;
+ @<Show cross-references to this section@>;
+ @<Output the code for the end of a section@>;
+}
+
+@ Sections beginning with the \.{CWEB} control sequence `\.{@@\ }' start in the
+output with the \TEX/ control sequence `\.{\\M}', followed by the section
+number. Similarly, `\.{@@*}' sections lead to the control sequence `\.{\\N}'.
+In this case there's an additional parameter, representing one plus the
+specified depth, immediately after the \.{\\N}.
+If the section has changed, we put \.{\\*} just after the section number.
+
+@<Output the code for the beginning...@>=
+if (*(loc-1)!='*') out_str("\\M");
+@.\\M@>
+else {
+ while (*loc == ' ') loc++;
+ if (*loc=='*') { /* ``top'' level */
+ sec_depth = -1;
+ loc++;
+ }
+ else {
+ for (sec_depth=0; xisdigit(*loc);loc++)
+ sec_depth = sec_depth*10 + (*loc) -'0';
+ }
+ while (*loc == ' ') loc++; /* remove spaces before group title */
+ group_found=1;
+ out_str("\\N");
+@.\\N@>
+ {@+ char s[32];@+sprintf(s,"{%d}",sec_depth+1);@+out_str(s);@+}
+ if (show_progress)
+ printf("*%d",section_count); update_terminal; /* print a progress report */
+}
+out_str("{");out_section(section_count); out_str("}");
+
+@ In the \TEX/ part of a section, we simply copy the source text, except that
+index entries are not copied and \CEE/ text within \pb\ is translated.
+
+@<Translate the \T...@>= do {
+ next_control=copy_TeX();
+ switch (next_control) {
+ case '|': init_stack; output_C(); break;
+ case '@@': out('@@'); break;
+ case TeX_string: case noop:
+ case xref_roman: case xref_wildcard: case xref_typewriter:
+ case section_name: loc-=2; next_control=get_next(); /* skip to \.{@@>} */
+ if (next_control==TeX_string)
+ err_print("! TeX string should be in C text only"); break;
+@.TeX string should be...@>
+ case thin_space: case math_break: case ord:
+ case line_break: case big_line_break: case no_line_break: case join:
+ case pseudo_semi: case macro_arg_open: case macro_arg_close:
+ case output_defs_code:
+ err_print("! You can't do that in TeX text"); break;
+@.You can't do that...@>
+ }
+} while (next_control<format_code);
+
+@ When we get to the following code we have |next_control>=format_code|, and
+the token memory is in its initial empty state.
+
+@<Translate the d...@>=
+space_checked=0;
+while (next_control<=definition) { /* |format_code| or |definition| */
+ init_stack;
+ if (next_control==definition) @<Start a macro definition@>@;
+ else @<Start a format definition@>;
+ outer_parse(); finish_C(format_visible); format_visible=1;
+ doing_format=0;
+}
+
+@ The |finish_C| procedure outputs the translation of the current
+scraps, preceded by the control sequence `\.{\\B}' and followed by the
+control sequence `\.{\\par}'. It also restores the token and scrap
+memories to their initial empty state.
+
+A |force| token is appended to the current scraps before translation
+takes place, so that the translation will normally end with \.{\\6} or
+\.{\\7} (the \TEX/ macros for |force| and |big_force|). This \.{\\6} or
+\.{\\7} is replaced by the concluding \.{\\par} or by \.{\\Y\\par}.
+
+@<Predecl...@>=
+void finish_C();
+
+@ @c
+void
+finish_C(visible) /* finishes a definition or a \CEE/ part */
+ boolean visible; /* nonzero if we should produce \TEX/ output */
+{
+ text_pointer p; /* translation of the scraps */
+ if (visible) {
+ out_str("\\B"); app_tok(force); app_scrap(insert,no_math);
+ p=translate();
+@.\\B@>
+ app(tok_flag+(int)(p-tok_start)); make_output(); /* output the list */
+ if (out_ptr>out_buf+1)
+ if (*(out_ptr-1)=='\\')
+@.\\6@>
+@.\\7@>
+@.\\Y@>
+ if (*out_ptr=='6') out_ptr-=2;
+ else if (*out_ptr=='7') *out_ptr='Y';
+ out_str("\\par"); finish_line();
+ }
+ if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
+ if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
+ if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
+ tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info;
+ /* forget the tokens and the scraps */
+}
+
+@ Keeping in line with the conventions of the \CEE/ preprocessor (and
+otherwise contrary to the rules of \.{CWEB}) we distinguish here
+between the case that `\.(' immediately follows an identifier and the
+case that the two are separated by a space. In the latter case, and
+if the identifier is not followed by `\.(' at all, the replacement
+text starts immediately after the identifier. In the former case,
+it starts after we scan the matching `\.)'.
+
+@<Start a macro...@>= {
+ if (save_line!=out_line || save_place!=out_ptr || space_checked) app(backup);
+ if(!space_checked){emit_space_if_needed;save_position;}
+ app_str("\\D"); /* this will produce `\&{define }' */
+@.\\D@>
+ if ((next_control=get_next())!=identifier)
+ err_print("! Improper macro definition");
+@.Improper macro definition@>
+ else {
+ app('$'); app_cur_id(0);
+ if (*loc=='(')
+ reswitch: switch (next_control=get_next()) {
+ case '(': case ',': app(next_control); goto reswitch;
+ case identifier: app_cur_id(0); goto reswitch;
+ case ')': app(next_control); next_control=get_next(); break;
+ default: err_print("! Improper macro definition"); break;
+ }
+ else next_control=get_next();
+ app_str("$ "); app(break_space);
+ app_scrap(dead,no_math); /* scrap won't take part in the parsing */
+ }
+}
+
+@ @<Start a format...@>= {
+ doing_format=1;
+ if(*(loc-1)=='s' || *(loc-1)=='S') format_visible=0;
+ if(!space_checked){emit_space_if_needed;save_position;}
+ app_str("\\F"); /* this will produce `\&{format }' */
+@.\\F@>
+ next_control=get_next();
+ if (next_control==identifier) {
+ app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
+ app(' ');
+ app(break_space); /* this is syntactically separate from what follows */
+ next_control=get_next();
+ if (next_control==identifier) {
+ app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
+ app_scrap(exp,maybe_math); app_scrap(semi,maybe_math);
+ next_control=get_next();
+ }
+ }
+ if (scrap_ptr!=scrap_info+2) err_print("! Improper format definition");
+@.Improper format definition@>
+}
+
+@ Finally, when the \TEX/ and definition parts have been treated, we have
+|next_control>=begin_C|. We will make the global variable |this_section|
+point to the current section name, if it has a name.
+
+@<Global...@>=
+name_pointer this_section; /* the current section name, or zero */
+
+@ @<Translate the \CEE/...@>=
+this_section=name_dir;
+if (next_control<=section_name) {
+ emit_space_if_needed; init_stack;
+ if (next_control==begin_C) next_control=get_next();
+ else {
+ this_section=cur_section;
+ @<Check that '=' or '==' follows this section name, and
+ emit the scraps to start the section definition@>;
+ }
+ while (next_control<=section_name) {
+ outer_parse();
+ @<Emit the scrap for a section name if present@>;
+ }
+ finish_C(1);
+}
+
+@ The title of the section and an $\E$ or $\mathrel+\E$ are made
+into a scrap that should not take part in the parsing.
+
+@<Check that '='...@>=
+do next_control=get_next();
+ while (next_control=='+'); /* allow optional `\.{+=}' */
+if (next_control!='=' && next_control!=eq_eq)
+ err_print("! You need an = sign after the section name");
+@.You need an = sign...@>
+ else next_control=get_next();
+if (out_ptr>out_buf+1 && *out_ptr=='Y' && *(out_ptr-1)=='\\') app(backup);
+ /* the section name will be flush left */
+@.\\Y@>
+app(section_flag+(int)(this_section-name_dir));
+cur_xref=(xref_pointer)this_section->xref;
+if(cur_xref->num==file_flag) cur_xref=cur_xref->xlink;
+app_str("${}");
+if (cur_xref->num!=section_count+def_flag) {
+ app_str("\\mathrel+"); /*section name is multiply defined*/
+ this_section=name_dir; /*so we won't give cross-reference info here*/
+}
+app_str("\\E"); /* output an equivalence sign */
+@.\\E@>
+app_str("{}$");
+app(force); app_scrap(dead,no_math);
+ /* this forces a line break unless `\.{@@+}' follows */
+
+@ @<Emit the scrap...@>=
+if (next_control<section_name) {
+ err_print("! You can't do that in C text");
+@.You can't do that...@>
+ next_control=get_next();
+}
+else if (next_control==section_name) {
+ app(section_flag+(int)(cur_section-name_dir));
+ app_scrap(section_scrap,maybe_math);
+ next_control=get_next();
+}
+
+@ Cross references relating to a named section are given
+after the section ends.
+
+@<Show cross...@>=
+if (this_section>name_dir) {
+ cur_xref=(xref_pointer)this_section->xref;
+ if (cur_xref->num==file_flag){an_output=1;cur_xref=cur_xref->xlink;}
+ else an_output=0;
+ if (cur_xref->num>def_flag)
+ cur_xref=cur_xref->xlink; /* bypass current section number */
+ footnote(def_flag); footnote(cite_flag); footnote(0);
+}
+
+@ The |footnote| procedure gives cross-reference information about
+multiply defined section names (if the |flag| parameter is
+|def_flag|), or about references to a section name
+(if |flag==cite_flag|), or to its uses (if |flag==0|). It assumes that
+|cur_xref| points to the first cross-reference entry of interest, and it
+leaves |cur_xref| pointing to the first element not printed. Typical outputs:
+`\.{\\A101.}'; `\.{\\Us 370\\ET1009.}';
+`\.{\\As 8, 27\\*\\ETs64.}'.
+
+Note that the output of \.{CWEAVE} is not English-specific; users may
+supply new definitions for the macros \.{\\A}, \.{\\As}, etc.
+
+@<Predecl...@>=
+void footnote();
+
+@ @c
+void
+footnote(flag) /* outputs section cross-references */
+sixteen_bits flag;
+{
+ xref_pointer q; /* cross-reference pointer variable */
+ if (cur_xref->num<=flag) return;
+ finish_line(); out('\\');
+@.\\A@>
+@.\\Q@>
+@.\\U@>
+ out(flag==0? 'U': flag==cite_flag? 'Q': 'A');
+ @<Output all the section numbers on the reference list |cur_xref|@>;
+ out('.');
+}
+
+@ The following code distinguishes three cases, according as the number
+of cross-references is one, two, or more than two. Variable |q| points
+to the first cross-reference, and the last link is a zero.
+
+@<Output all the section numbers...@>=
+q=cur_xref; if (q->xlink->num>flag) out('s'); /* plural */
+while (1) {
+ out_section(cur_xref->num-flag);
+ cur_xref=cur_xref->xlink; /* point to the next cross-reference to output */
+ if (cur_xref->num<=flag) break;
+ if (cur_xref->xlink->num>flag) out_str(", "); /* not the last */
+ else {out_str("\\ET"); /* the last */
+@.\\ET@>
+ if (cur_xref != q->xlink) out('s'); /* the last of more than two */
+ }
+}
+
+@ @<Output the code for the end of a section@>=
+out_str("\\fi"); finish_line();
+@.\\fi@>
+flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
+
+@** Phase three processing.
+We are nearly finished! \.{CWEAVE}'s only remaining task is to write out the
+index, after sorting the identifiers and index entries.
+
+If the user has set the |no_xref| flag (the \.{-x} option on the command line),
+just finish off the page, omitting the index, section name list, and table of
+contents.
+
+@<Predecl...@>=
+void phase_three();
+
+@ @c
+void
+phase_three() {
+if (no_xref) {
+ finish_line();
+ out_str("\\end");
+@.\\end@>
+ finish_line();
+}
+else {
+ phase=3; if (show_progress) printf("\nWriting the index...");
+@.Writing the index...@>
+ finish_line();
+ if ((idx_file=fopen(idx_file_name,"w"))==NULL)
+ fatal("! Cannot open index file ",idx_file_name);
+@.Cannot open index file@>
+ if (change_exists) {
+ @<Tell about changed sections@>; finish_line(); finish_line();
+ }
+ out_str("\\inx"); finish_line();
+@.\\inx@>
+ active_file=idx_file; /* change active file to the index file */
+ @<Do the first pass of sorting@>;
+ @<Sort and output the index@>;
+ finish_line(); fclose(active_file); /* finished with |idx_file| */
+ active_file=tex_file; /* switch back to |tex_file| for a tic */
+ out_str("\\fin"); finish_line();
+@.\\fin@>
+ if ((scn_file=fopen(scn_file_name,"w"))==NULL)
+ fatal("! Cannot open section file ",scn_file_name);
+@.Cannot open section file@>
+ active_file=scn_file; /* change active file to section listing file */
+ @<Output all the section names@>;
+ finish_line(); fclose(active_file); /* finished with |scn_file| */
+ active_file=tex_file;
+ if (group_found) out_str("\\con");@+else out_str("\\end");
+@.\\con@>
+@.\\end@>
+ finish_line();
+ fclose(active_file);
+}
+if (show_happiness) printf("\nDone.");
+check_complete(); /* was all of the change file used? */
+}
+
+@ Just before the index comes a list of all the changed sections, including
+the index section itself.
+
+@<Global...@>=
+sixteen_bits k_section; /* runs through the sections */
+
+@ @<Tell about changed sections@>= {
+ /* remember that the index is already marked as changed */
+ k_section=0;
+ while (!changed_section[++k_section]);
+ out_str("\\ch ");
+@.\\ch@>
+ out_section(k_section);
+ while (k_section<section_count) {
+ while (!changed_section[++k_section]);
+ out_str(", "); out_section(k_section);
+ }
+ out('.');
+}
+
+@ A left-to-right radix sorting method is used, since this makes it easy to
+adjust the collating sequence and since the running time will be at worst
+proportional to the total length of all entries in the index. We put the
+identifiers into 102 different lists based on their first characters.
+(Uppercase letters are put into the same list as the corresponding lowercase
+letters, since we want to have `$t<\\{TeX}<\&{to}$'.) The
+list for character |c| begins at location |bucket[c]| and continues through
+the |blink| array.
+
+@<Global...@>=
+name_pointer bucket[256];
+name_pointer next_name; /* successor of |cur_name| when sorting */
+name_pointer blink[max_names]; /* links in the buckets */
+
+@ To begin the sorting, we go through all the hash lists and put each entry
+having a nonempty cross-reference list into the proper bucket.
+
+@<Do the first pass...@>= {
+int c;
+for (c=0; c<=255; c++) bucket[c]=NULL;
+for (h=hash; h<=hash_end; h++) {
+ next_name=*h;
+ while (next_name) {
+ cur_name=next_name; next_name=cur_name->link;
+ if (cur_name->xref!=(char*)xmem) {
+ c=(eight_bits)((cur_name->byte_start)[0]);
+ if (xisupper(c)) c=tolower(c);
+ blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
+ }
+ }
+}
+}
+
+@ During the sorting phase we shall use the |cat| and |trans| arrays from
+\.{CWEAVE}'s parsing algorithm and rename them |depth| and |head|. They now
+represent a stack of identifier lists for all the index entries that have
+not yet been output. The variable |sort_ptr| tells how many such lists are
+present; the lists are output in reverse order (first |sort_ptr|, then
+|sort_ptr-1|, etc.). The |j|th list starts at |head[j]|, and if the first
+|k| characters of all entries on this list are known to be equal we have
+|depth[j]==k|.
+
+@ @<Rest of |trans_plus| union@>=
+name_pointer Head;
+
+@ @d depth cat /* reclaims memory that is no longer needed for parsing */
+@d head trans_plus.Head /* ditto */
+@f sort_pointer int
+@d sort_pointer scrap_pointer /* ditto */
+@d sort_ptr scrap_ptr /* ditto */
+@d max_sorts max_scraps /* ditto */
+
+@<Global...@>=
+eight_bits cur_depth; /* depth of current buckets */
+char *cur_byte; /* index into |byte_mem| */
+sixteen_bits cur_val; /* current cross-reference number */
+sort_pointer max_sort_ptr; /* largest value of |sort_ptr| */
+
+@ @<Set init...@>=
+max_sort_ptr=scrap_info;
+
+@ The desired alphabetic order is specified by the |collate| array; namely,
+$|collate|[0]<|collate|[1]<\cdots<|collate|[100]$.
+
+@<Global...@>=
+eight_bits collate[102+128]; /* collation order */
+@^high-bit character handling@>
+
+@ We use the order $\hbox{null}<\.\ <\hbox{other characters}<{}$\.\_${}<
+\.A=\.a<\cdots<\.Z=\.z<\.0<\cdots<\.9.$ Warning: The collation mapping
+needs to be changed if ASCII code is not being used.
+@^ASCII code dependencies@>
+@^high-bit character handling@>
+
+We initialize |collate| by copying a few characters at a time, because
+some \CEE/ compilers choke on long strings.
+
+@<Set init...@>=
+collate[0]=0;
+strcpy(collate+1," \1\2\3\4\5\6\7\10\11\12\13\14\15\16\17");
+/* 16 characters + 1 = 17 */
+strcpy(collate+17,"\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37");
+/* 16 characters + 17 = 33 */
+strcpy(collate+33,"!\42#$%&'()*+,-./:;<=>?@@[\\]^`{|}~_");
+/* 32 characters + 33 = 65 */
+strcpy(collate+65,"abcdefghijklmnopqrstuvwxyz0123456789");
+/* (26 + 10) characters + 65 = 101 */
+strcpy(collate+101,"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217");
+/* 16 characters + 101 = 117 */
+strcpy(collate+117,"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237");
+/* 16 characters + 117 = 133 */
+strcpy(collate+133,"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257");
+/* 16 characters + 133 = 149 */
+strcpy(collate+149,"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277");
+/* 16 characters + 149 = 165 */
+strcpy(collate+165,"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317");
+/* 16 characters + 165 = 181 */
+strcpy(collate+181,"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337");
+/* 16 characters + 181 = 197 */
+strcpy(collate+197,"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357");
+/* 16 characters + 197 = 213 */
+strcpy(collate+213,"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377");
+/* 16 characters + 213 = 229 */
+
+@ Procedure |unbucket| goes through the buckets and adds nonempty lists
+to the stack, using the collating sequence specified in the |collate| array.
+The parameter to |unbucket| tells the current depth in the buckets.
+Any two sequences that agree in their first 255 character positions are
+regarded as identical.
+
+@d infinity 255 /* $\infty$ (approximately) */
+
+@<Predecl...@>=
+void unbucket();
+
+@ @c
+void
+unbucket(d) /* empties buckets having depth |d| */
+eight_bits d;
+{
+ int c; /* index into |bucket|; cannot be a simple |char| because of sign
+ comparison below*/
+ for (c=100+128; c>= 0; c--) if (bucket[collate[c]]) {
+@^high-bit character handling@>
+ if (sort_ptr>=scrap_info_end) overflow("sorting");
+ sort_ptr++;
+ if (sort_ptr>max_sort_ptr) max_sort_ptr=sort_ptr;
+ if (c==0) sort_ptr->depth=infinity;
+ else sort_ptr->depth=d;
+ sort_ptr->head=bucket[collate[c]]; bucket[collate[c]]=NULL;
+ }
+}
+
+@ @<Sort and output...@>=
+sort_ptr=scrap_info; unbucket(1);
+while (sort_ptr>scrap_info) {
+ cur_depth=sort_ptr->depth;
+ if (blink[sort_ptr->head-name_dir]==0 || cur_depth==infinity)
+ @<Output index entries for the list at |sort_ptr|@>@;
+ else @<Split the list at |sort_ptr| into further lists@>;
+}
+
+@ @<Split the list...@>= {
+ eight_bits c;
+ next_name=sort_ptr->head;
+ do {
+ cur_name=next_name; next_name=blink[cur_name-name_dir];
+ cur_byte=cur_name->byte_start+cur_depth;
+ if (cur_byte==(cur_name+1)->byte_start) c=0; /* hit end of the name */
+ else {
+ c=(eight_bits) *cur_byte;
+ if (xisupper(c)) c=tolower(c);
+ }
+ blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
+ } while (next_name);
+ --sort_ptr; unbucket(cur_depth+1);
+}
+
+@ @<Output index...@>= {
+ cur_name=sort_ptr->head;
+ do {
+ out_str("\\I");
+@.\\I@>
+ @<Output the name at |cur_name|@>;
+ @<Output the cross-references at |cur_name|@>;
+ cur_name=blink[cur_name-name_dir];
+ } while (cur_name);
+ --sort_ptr;
+}
+
+@ @<Output the name...@>=
+switch (cur_name->ilk) {
+ case normal: case func_template: if (is_tiny(cur_name)) out_str("\\|");
+ else {char *j;
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ if (xislower(*j)) goto lowcase;
+ out_str("\\."); break;
+lowcase: out_str("\\\\");
+ }
+ break;
+@.\\|@>
+@.\\.@>
+@.\\\\@>
+ case wildcard: out_str("\\9");@+ goto not_an_identifier;
+@.\\9@>
+ case typewriter: out_str("\\.");
+@.\\.@>
+ case roman: not_an_identifier: out_name(cur_name,0); goto name_done;
+ case custom: {char *j; out_str("$\\");
+ for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
+ out(*j=='_'? 'x': *j=='$'? 'X': *j);
+ out('$');
+ goto name_done;
+ }
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name,1);
+name_done:@;
+
+@ Section numbers that are to be underlined are enclosed in
+`\.{\\[}$\,\ldots\,$\.]'.
+
+@<Output the cross-references...@>=
+@<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>;
+do {
+ out_str(", "); cur_val=cur_xref->num;
+ if (cur_val<def_flag) out_section(cur_val);
+ else {out_str("\\["); out_section(cur_val-def_flag); out(']');}
+@.\\[@>
+ cur_xref=cur_xref->xlink;
+} while (cur_xref!=xmem);
+out('.'); finish_line();
+
+@ List inversion is best thought of as popping elements off one stack and
+pushing them onto another. In this case |cur_xref| will be the head of
+the stack that we push things onto.
+@<Global...@>=
+xref_pointer next_xref, this_xref;
+ /* pointer variables for rearranging a list */
+
+@ @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>=
+this_xref=(xref_pointer)cur_name->xref; cur_xref=xmem;
+do {
+ next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
+ cur_xref=this_xref; this_xref=next_xref;
+} while (this_xref!=xmem);
+
+@ The following recursive procedure walks through the tree of section names and
+prints them.
+@^recursion@>
+
+@<Predecl...@>=
+void section_print();
+
+@ @c
+void
+section_print(p) /* print all section names in subtree |p| */
+name_pointer p;
+{
+ if (p) {
+ section_print(p->llink); out_str("\\I");
+@.\\I@>
+ tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack;
+ app(p-name_dir+section_flag); make_output();
+ footnote(cite_flag);
+ footnote(0); /* |cur_xref| was set by |make_output| */
+ finish_line();@/
+ section_print(p->rlink);
+ }
+}
+
+@ @<Output all the section names@>=section_print(root)
+
+@ Because on some systems the difference between two pointers is a |long|
+rather than an |int|, we use \.{\%ld} to print these quantities.
+
+@c
+void
+print_stats() {
+ printf("\nMemory usage statistics:\n");
+@.Memory usage statistics:@>
+ printf("%ld names (out of %ld)\n",
+ (long)(name_ptr-name_dir),(long)max_names);
+ printf("%ld cross-references (out of %ld)\n",
+ (long)(xref_ptr-xmem),(long)max_refs);
+ printf("%ld bytes (out of %ld)\n",
+ (long)(byte_ptr-byte_mem),(long)max_bytes);
+ printf("Parsing:\n");
+ printf("%ld scraps (out of %ld)\n",
+ (long)(max_scr_ptr-scrap_info),(long)max_scraps);
+ printf("%ld texts (out of %ld)\n",
+ (long)(max_text_ptr-tok_start),(long)max_texts);
+ printf("%ld tokens (out of %ld)\n",
+ (long)(max_tok_ptr-tok_mem),(long)max_toks);
+ printf("%ld levels (out of %ld)\n",
+ (long)(max_stack_ptr-stack),(long)stack_size);
+ printf("Sorting:\n");
+ printf("%ld levels (out of %ld)\n",
+ (long)(max_sort_ptr-scrap_info),(long)max_scraps);
+}
+
+@** Index.
+If you have read and understood the code for Phase III above, you know what
+is in this index and how it got here. All sections in which an identifier is
+used are listed with that identifier, except that reserved words are
+indexed only when they appear in format definitions, and the appearances
+of identifiers in section names are not indexed. Underlined entries
+correspond to where the identifier was declared. Error messages, control
+sequences put into the output, and a few
+other things like ``recursion'' are indexed here too.
diff --git a/Build/source/texk/web2c/cwebdir/cweb.1 b/Build/source/texk/web2c/cwebdir/cweb.1
new file mode 100644
index 00000000000..ad41c427ead
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweb.1
@@ -0,0 +1,138 @@
+.TH CWEB 1L 2002-Apr-13
+.
+.SH NAME
+ctangle, cweave \- translate CWEB to C and/or TeX
+.
+.SH SYNOPSIS
+.na
+.B ctangle
+[
+.B \-bhp
+] [
+.B +s
+] webfile[.w] [changefile[.ch]] [outputfile[.c]]
+.br
+.B cweave
+[
+.B \-befhpx
+] [
+.B +s
+] webfile[.w] [changefile[.ch]] [outputfile[.tex]]
+.ad
+.
+.SH DESCRIPTION
+The
+.I 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.
+.PP
+The
+.I 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.
+.PP
+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.
+.PP
+The command line should have one, two, or three names on it.
+The first is taken as the CWEB file (and .w is added if there is no
+extension).
+If that file cannot be opened, the extension .web is tried instead.
+(But .w is recommended, since .web usually implies Pascal.)
+If there is a second name, it is a change file (and .ch is added if there is
+no extension).
+The change file overrides parts of the WEB file,
+as described in the documentation.
+If there is a third name, it overrides
+the default name of the output file, which is ordinarily the same as
+the name of the input file (but on the current directory) with the
+extension .c or .tex.
+.PP
+Options in the command line may be either turned off with\ \-
+(if they are on by default) or turned on with\ + (if they are off by
+default).
+In fact, the options are processed from left to right,
+so a sequence like -f\ +f corresponds to +f (which is the default).
+.PP
+The
+.B \-b
+option suppresses the banner line that normally appears on your terminal
+when ctangle or cweave begins.
+The
+.B \-h
+option suppresses the happy message that normally appears if the processing
+was successful.
+The
+.B \-p
+option suppresses progress reports (starred module numbers) as the processing
+takes place.
+If you say -bhp, you get nothing but error messages.
+.PP
+The
+.B +s
+option prints statistics about memory usage at the end of a run
+(assuming that the programs have been compiled with the -DSTAT switch).
+.PP
+There are three other options applicable to
+.I cweave
+only:
+.B \-f
+means do not force a newline after every statement in the formatted output.
+.B \-e
+inhibits the enclosure of C\ material formatted by
+.I cweave
+in brackets
+\ePB{...}.
+Such brackets are normally inserted so that special hooks
+can be used by
+.I cweb-latex
+and similar programs.
+.B \-x
+means omit the index and table of contents.
+.
+.SH FILES
+.TP
+/usr/local/lib/tex/inputs/cwebmac.tex
+TeX macros used by cweave output.
+.TP
+/usr/local/src/cweb/cwebman.tex
+The user manual.
+.TP
+/usr/local/src/cweb/examples/wc.w
+An introductory example.
+.TP
+/usr/local/src/cweb/examples/wmerge.w
+Patch program based on CWEB-style change files.
+.TP
+/usr/local/lib/cweb
+Directory for cweb "include" files.
+.
+.SH "SEE ALSO"
+.TP
+.I Literate Programming
+by D. E. Knuth
+.TP
+.I Weaving a Program
+by Wayne Sewell
+.TP
+.I The CWEB System of Structured Documentation
+by Donald E. Knuth and Silvio Levy (hardcopy version of cwebman.tex
+and the source code listings)
+.TP
+tex(1), cc(1)
+.
+.SH AUTHORS
+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.
+Knuth began using CWEB and made further refinements.
+Many other helpers are acknowledged in the CWEB manual.
+
diff --git a/Build/source/texk/web2c/cwebdir/cweb.el b/Build/source/texk/web2c/cwebdir/cweb.el
new file mode 100644
index 00000000000..b7cfb2ee535
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cweb.el
@@ -0,0 +1,215 @@
+;; This file contains extensions to GNU-Emacs, to wit:
+; (1) some WEB-oriented functions that are also of general use
+; (2) changes to the GNU-distributed TeX mode
+; (3) definitions of simple WEB and CWEB modes
+
+; To use: Put this in your EMACS-lisp library and say (load-library "cweb")
+; in your .emacs init file.
+
+; Contributed by Don Knuth, July 1990
+
+;; OK, here's part (1): some WEB-oriented functions whose main purpose is
+; to maintain a stack of module names that are "pending" as you are writing
+; a program. When you first think of a module that needs to be written later,
+; put it into the pending list (by typing CTL-Z instead of @> after the
+; name). Later you can say CTL-\ to retrieve a pending name (and if
+; you want to cycle through the pending names, ESC-y after CTL-\ will
+; do it, just as ESC-y works after a yank).
+; After you've said CTL-\, the current region is the name just removed from
+; the pending list. If you change your mind, you can put it back again by
+; saying ESC-\. If you had put it into the pending list by mistake, you
+; can get rid of it by using the normal CTL-W operation (kill-region).
+; The following code binds the new commands to CTL-Z, CTL-\, and ESC-\
+; in all modes. You may prefer other bindings, of course.
+; CTL-Z is normally "suspend emacs", but it is best not used when emacs
+; has its own window as it usually does nowadays; if you need the
+; old CTL-Z, you might rather bind it to CTL-X CTL-Z.
+; CTL-\ is normally undefined.
+; ESC-\ is normally "delete space", but ESC-space DEL does that easily too.
+
+(defvar pending-list nil
+ "List of strings (usually WEB module names) still pending.")
+
+(defun into-pending-list (beg end)
+ "Copy region into pending-list."
+ (interactive "r")
+ (indicate-region)
+ (setq pending-list (cons (buffer-substring beg end) pending-list)))
+
+(defun new-module-name-pending ()
+ "Insert @> to complete a module name, then put it into pending-list."
+ (interactive)
+ (insert "@>")
+ (push-mark)
+ (if (search-backward "@<" nil t)
+ (progn
+ (exchange-point-and-mark)
+ (into-pending-list (point) (mark))
+ )
+ (message "There's no @< to begin the module name!")))
+(global-set-key "\C-z" 'new-module-name-pending)
+
+(defun pop-pending-list (arg)
+ "Remove first element of pending-list and insert it as current region.
+With argument, put point at left; otherwise point will follow the insertion.
+Say \\[new-yank-pop] to replace this by another element of the list.
+Say \\[into-pending-list] to put it back in the list."
+ (interactive "*P")
+ (if (consp pending-list)
+ (progn
+ (push-mark (point))
+ (insert (car pending-list))
+ (setq pending-list (cdr pending-list))
+ (if arg
+ (exchange-point-and-mark)))
+ (message "Nothing is pending.")
+ (setq this-command nil)))
+(global-set-key "\C-\\" 'pop-pending-list)
+(global-set-key "\M-\\" 'into-pending-list)
+
+(defun new-yank-pop (arg)
+ "If previous command was \\[pop-pending-list], pop a different string;
+otherwise do an ordinary Meta-y."
+ (interactive "*p")
+ (if (eq last-command 'pop-pending-list)
+ (let (xch)
+ (setq xch (< (point) (mark)))
+ (setq pending-list (append pending-list
+ (list (buffer-substring (point) (mark)))))
+ (delete-region (point) (mark))
+ (setq this-command 'pop-pending-list)
+ (pop-pending-list xch))
+ (yank-pop arg)))
+(global-set-key "\M-y" 'new-yank-pop)
+
+(defun indicate-region ()
+ "Bounce cursor to mark and back again"
+ (let ((point-save (point)))
+ (unwind-protect
+ (progn (goto-char (mark))
+ (sit-for 0 300)) ;; wait 300 milliseconds
+ (goto-char point-save))))
+
+; I prefer to change the standard copy-region command to the following,
+; which gives me visual feedback about what I've copied to the kill ring:
+(defun indicate-and-copy-region (beg end)
+ "Indicate current region, then copy it to the kill ring."
+ (interactive "r")(indicate-region)(copy-region-as-kill beg end))
+(global-set-key "\M-w" 'indicate-and-copy-region)
+
+; Here's another convenient command, bound to the usually unused ESC-".
+(defun ditto (arg)
+ "Copy ARG characters from the line above."
+ (interactive "*p")
+ (let (ch)
+ (while (> arg 0)
+ (setq temporary-goal-column (current-column))
+ (save-excursion
+ (previous-line 1)
+ (setq ch (following-char)))
+ (insert ch)
+ (setq arg (1- arg)))))
+(global-set-key "\M-\"" 'ditto)
+
+;; OK, here's part (2): Changes to TeX mode.
+; The WEB modes below are very much like TeX mode, but some improvements were
+; desirable in TeX mode:
+; I made newline act as it does in indented-text mode, since this
+; works nicely for both TeX and WEB (Pascal or C code).
+; I made RET check for unmatched delimiters if it ends a paragraph.
+; Otherwise TeX mode remains as it was before.
+
+(setq TeX-mode-map (make-sparse-keymap))
+(define-key TeX-mode-map "\C-c\C-k" 'TeX-kill-job)
+(define-key TeX-mode-map "\C-c\C-l" 'TeX-recenter-output-buffer)
+(define-key TeX-mode-map "\C-c\C-q" 'TeX-show-print-queue)
+(define-key TeX-mode-map "\C-c\C-p" 'TeX-print)
+(define-key TeX-mode-map "\"" 'TeX-insert-quote)
+(define-key TeX-mode-map "\e}" 'up-list)
+(define-key TeX-mode-map "\e{" 'TeX-insert-braces)
+(define-key TeX-mode-map "\C-c\C-r" 'TeX-region)
+(define-key TeX-mode-map "\C-c\C-b" 'TeX-buffer)
+(define-key TeX-mode-map "\C-c\C-f" 'TeX-close-LaTeX-block)
+(define-key TeX-mode-map "\r" 'TeX-newline)
+(define-key TeX-mode-map "\t" 'indent-relative)
+(setq TeX-mode-hook '(lambda ()
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'indent-relative-maybe)))
+
+(defun TeX-newline (arg)
+"If previous character is newline and no ARG, check for unbalanced braces
+and/or dollar signs in previous paragraph. If ARG is \\[universal-argument],
+do a single newline; otherwise do ordinary newline."
+ (interactive "*P")
+ (if (and (eq (preceding-char) ?\n) (not arg))
+ (TeX-check-paragraph)
+ (if (listp arg)
+ (newline)
+ (newline arg))))
+
+(defun TeX-check-paragraph ()
+"Insert a newline following a newline, breaking a paragraph for TeX.
+Check for mismatched delimiters in paragraph being terminated."
+ (interactive)
+ (if (TeX-validate-paragraph
+ (save-excursion
+ (search-backward "\n\n" nil 'move)
+ (point))
+ (point))
+ (insert ?\n)
+ (insert ?\n)
+ (error "Mismatched delimiters in that paragraph?")))
+
+;; and now, part (3): WEB and CWEB modes.
+; These are like plain TeX mode except that the automatic conversion of
+; " to `` or '' is disabled. (Personally I never liked that feature anyway,
+; since it's easy to get used to typing `` and ''. In WEB modes, the
+; feature soon becomes intolerable, unless you never use string constants!)
+; Another thing distinguishing WEB mode from TeX is ESC-p and ESC-n, to
+; move to previous or next module. These keys are usually unbound, except
+; when processing email.
+
+(defun forward-module (arg)
+"Advance past next WEB module beginning; with ARG, repeat ARG times."
+ (interactive "p")
+ (move-to-module arg))
+(defun backward-module (arg)
+"Advance to previous WEB module beginning; with ARG, repeat ARG times."
+ (interactive "p")
+ (move-to-module (- arg)))
+(defun move-to-module (arg)
+ (while (> arg 0)
+ (re-search-forward "@ \\|@\\*\\|@\n")
+ (setq arg (1- arg)))
+ (while (< arg 0)
+ (re-search-backward "@ \\|@\\*\\|@\n")
+ (setq arg (1+ arg))))
+
+(defun web-mode ()
+ "Major mode like TeX mode plus \\[forward-module] and \\[backward-module]
+for relative module movement. The automatic \" feature is disabled."
+ (interactive)
+ (plain-tex-mode)
+ (local-set-key "\M-n" 'forward-module)
+ (local-set-key "\M-p" 'backward-module)
+ (local-set-key "\"" 'self-insert-command)
+ (setq mode-name "WEB")
+ (setq major-mode 'web-mode)
+ (run-hooks 'web-mode-hook))
+(setq auto-mode-alist (cons '("\\.web$" . web-mode) auto-mode-alist))
+
+(defun cweb-mode ()
+ "Major mode like TeX mode plus \\[forward-module] and \\[backward-module]
+for relative module movement. The automatic \" feature is disabled."
+ (interactive)
+ (plain-tex-mode)
+ (local-set-key "\M-n" 'forward-module)
+ (local-set-key "\M-p" 'backward-module)
+ (local-set-key "\"" 'self-insert-command)
+ (setq comment-start nil)
+ (modify-syntax-entry ?% "@")
+ (setq mode-name "CWEB")
+ (setq major-mode 'cweb-mode)
+ (run-hooks 'cweb-mode-hook))
+(setq auto-mode-alist (cons '("\\.w$" . cweb-mode) auto-mode-alist))
+(setq auto-mode-alist (cons '("\\.ch$" . cweb-mode) auto-mode-alist))
diff --git a/Build/source/texk/web2c/cwebdir/cwebmac.tex b/Build/source/texk/web2c/cwebdir/cwebmac.tex
new file mode 100644
index 00000000000..8eca77d71cd
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cwebmac.tex
@@ -0,0 +1,539 @@
+% standard macros for CWEB listings (in addition to plain.tex)
+% Version 3.64 --- February 2002
+\ifx\documentstyle\undefined\else\endinput\fi % LaTeX will use other macros
+\xdef\fmtversion{\fmtversion+CWEB3.64}
+\chardef\cwebversion=3 \chardef\cwebrevision=64
+\newif\ifpdf
+\ifx\pdf+\pdftrue\fi
+% Uncomment the following line if you want PDF goodies to be the default
+%\ifx\pdf-\else\pdftrue\fi
+\def\pdflinkcolor{0 0 1} % the RGB values for hyperlink color
+\newif\ifpdftex
+\ifx\pdfoutput\undefined \pdftexfalse \else\ifnum\pdfoutput=0 \pdftexfalse
+\else \pdftextrue \pdfoutput=1 \input pdfcolor \let\setcolor\pdfsetcolor \fi\fi
+\newif\ifacro \ifpdf\acrotrue\fi \ifpdftex\acrotrue\fi
+
+\let\:=\. % preserve a way to get the dot accent
+ % (all other accents will still work as usual)
+
+\parskip 0pt % no stretch between paragraphs
+\parindent 1em % for paragraphs and for the first line of C text
+
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\CEE/{{\mc C\spacefactor1000}}
+\def\UNIX/{{\mc U\kern-.05emNIX\spacefactor1000}}
+\def\TEX/{\TeX}
+\def\CPLUSPLUS/{{\mc C\PP\spacefactor1000}}
+\def\Cee{\CEE/} % for backward compatibility
+\def\9#1{}
+ % with this definition of \9 you can say @:sort key}{TeX code@>
+ % to alphabetize an index entry by the sort key but format with the TeX code
+\font\eightrm=cmr8
+\let\sc=\eightrm % for smallish caps (NOT a caps-and-small-caps font)
+\let\mainfont=\tenrm
+\let\cmntfont\tenrm
+%\font\tenss=cmss10 \let\cmntfont\tenss % alternative comment font
+\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\font\tentex=cmtex10 % TeX extended character set (used in strings)
+\fontdimen7\tentex=0pt % no double space after sentences
+
+\def\\#1{\leavevmode\hbox{\it#1\/\kern.05em}} % italic type for identifiers
+\def\|#1{\leavevmode\hbox{$#1$}} % one-letter identifiers look better this way
+\def\&#1{\leavevmode\hbox{\bf
+ \def\_{\kern.04em\vbox{\hrule width.3em height .6pt}\kern.08em}%
+ #1\/\kern.05em}} % boldface type for reserved words
+\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings
+ \let\\=\BS % backslash in a string
+ \let\{=\LB % left brace in a string
+ \let\}=\RB % right brace in a string
+ \let\~=\TL % tilde in a string
+ \let\ =\SP % space in a string
+ \let\_=\UL % underline in a string
+ \let\&=\AM % ampersand in a string
+ \let\^=\CF % circumflex in a string
+ #1\kern.05em}}
+\def\){{\tentex\kern-.05em}\discretionary{\hbox{\tentex\BS}}{}{}}
+\def\AT{@} % at sign for control text (not needed in versions >= 2.9)
+\def\ATL{\par\noindent\bgroup\catcode`\_=12 \postATL} % print @l in limbo
+\def\postATL#1 #2 {\bf letter \\{\uppercase{\char"#1}}
+ tangles as \tentex "#2"\egroup\par}
+\def\noATL#1 #2 {}
+\def\noatl{\let\ATL=\noATL} % suppress output from @l
+\def\ATH{{\acrofalse\X\kern-.5em:Preprocessor definitions\X}}
+\let\PB=\relax % hook for program brackets |...| in TeX part or section name
+
+\chardef\AM=`\& % ampersand character in a string
+\chardef\BS=`\\ % backslash in a string
+\chardef\LB=`\{ % left brace in a string
+\chardef\RB=`\} % right brace in a string
+\def\SP{{\tt\char`\ }} % (visible) space in a string
+\chardef\TL=`\~ % tilde in a string
+\chardef\UL=`\_ % underline character in a string
+\chardef\CF=`\^ % circumflex character in a string
+
+\newbox\PPbox % symbol for ++
+\setbox\PPbox=\hbox{\kern.5pt\raise1pt\hbox{\sevenrm+\kern-1pt+}\kern.5pt}
+\def\PP{\copy\PPbox}
+\newbox\MMbox \setbox\MMbox=\hbox{\kern.5pt\raise1pt\hbox{\sevensy\char0
+ \kern-1pt\char0}\kern.5pt}
+\def\MM{\copy\MMbox}
+\newbox\MGbox % symbol for ->
+\setbox\MGbox=\hbox{\kern-2pt\lower3pt\hbox{\teni\char'176}\kern1pt}
+\def\MG{\copy\MGbox}
+\def\MRL#1{\mathrel{\let\K==#1}}
+%\def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;#1\over{#2}}
+\let\GG=\gg
+\let\LL=\ll
+\let\NULL=\Lambda
+\mathchardef\AND="2026 % bitwise and; also \& (unary operator)
+\let\OR=\mid % bitwise or
+\let\XOR=\oplus % bitwise exclusive or
+\def\CM{{\sim}} % bitwise complement
+\newbox\MODbox \setbox\MODbox=\hbox{\eightrm\%}
+\def\MOD{\mathbin{\copy\MODbox}}
+\def\DC{\kern.1em{::}\kern.1em} % symbol for ::
+\def\PA{\mathbin{.*}} % symbol for .*
+\def\MGA{\mathbin{\MG*}} % symbol for ->*
+\def\this{\&{this}}
+
+\newbox\bak \setbox\bak=\hbox to -1em{} % backspace one em
+\newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace two ems
+
+\newcount\ind % current indentation in ems
+\def\1{\global\advance\ind by1\hangindent\ind em} % indent one more notch
+\def\2{\global\advance\ind by-1} % indent one less notch
+\def\3#1{\hfil\penalty#10\hfilneg} % optional break within a statement
+\def\4{\copy\bak} % backspace one notch
+\def\5{\hfil\penalty-1\hfilneg\kern2.5em\copy\bakk\ignorespaces}% optional break
+\def\6{\ifmmode\else\par % forced break
+ \hangindent\ind em\noindent\kern\ind em\copy\bakk\ignorespaces\fi}
+\def\7{\Y\6} % forced break and a little extra space
+\def\8{\hskip-\ind em\hskip 2em} % no indentation
+
+\newcount\gdepth % depth of current major group, plus one
+\newcount\secpagedepth
+\secpagedepth=3 % page breaks will occur for depths -1, 0, and 1
+\newtoks\gtitle % title of current major group
+\newskip\intersecskip \intersecskip=12pt minus 3pt % space between sections
+\let\yskip=\smallskip
+\def\?{\mathrel?}
+\def\note#1#2.{\Y\noindent{\hangindent2em%
+ \baselineskip10pt\eightrm#1~\ifacro{\pdfnote#2.}\else#2\fi.\par}}
+
+\newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD
+\newtoks\toksE \newtoks\toksF \newtoks\usersanitizer
+\newcount\countA \countA=0 \newcount\countB \countB=0
+\newcount\countC \countC=0
+\newif\iftokprocessed \newif\ifTnum \newif\ifinstr
+{\def\\{\global\let\spacechar= }\\ }
+
+\ifacro % The following are pdf macros
+\def\thewidth{\the\wd0 \space}
+\def\theheight{\the\ht\strutbox\space}
+\def\thedepth{\the\dp\strutbox\space}
+\ifpdftex
+ \ifx\pdfannotlink\undefined\let\pdfannotlink\pdfstartlink\fi% for pdfTeX 0.14
+ \def\pdflink#1#2{\hbox{\pdfannotlink height\ht\strutbox depth\dp\strutbox
+ attr{/Border [0 0 0]} goto num #1 \BlueGreen #1\Black\pdfendlink}}
+\else\def\pdflink#1#2{\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#1}%
+ \special{pdf: ec}}\special{pdf: ann width \thewidth height \theheight
+ depth \thedepth << /Type /Annot /Subtype /Link
+ /Border [0 0 0] /A << /S /GoTo /D (#2) >> >>}\box0\relax}\fi
+\def\pdfnote#1.{\setbox0=\hbox{\toksA={#1.}\toksB={}\maketoks}\the\toksA}
+\def\firstsecno#1.{\setbox0=\hbox{\toksA={#1.}\toksB={}%
+ \def\makenote{\addtokens\toksB{\the\toksC}\def\makenote{\toksD={}
+ \toksC={}\let\space\empty}\makenote}\maketoks}}
+\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+\def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}%
+ \ifcat\noexpand\first0\countB=`#1\else\countB=0\fi\toksA={#2}}
+\def\maketoks{\expandafter\poptoks\the\toksA|ENDTOKS|%
+ \ifnum\countB>`9 \countB=0 \fi
+ \ifnum\countB<`0
+ \ifnum0=\countC\else\makenote\fi
+ \ifx\first.\let\next=\maketoksdone\else
+ \let\next=\maketoks
+ \addtokens\toksB{\the\toksD}
+ \ifx\first,\addtokens\toksB{\space}\fi
+ \fi
+ \else \addtokens\toksC{\the\toksD}\global\countC=1\let\next=\maketoks
+ \fi
+ \next
+}
+\def\makenote{\addtokens\toksB
+ {\noexpand\pdflink{\the\toksC}{\romannumeral\the\toksC}}\toksC={}\global\countC=0}
+\def\maketoksdone{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\def\pdfURL#1#2{\ifpdftex\pdfannotlink height\ht\strutbox depth\dp\strutbox
+ attr {/Border [0 0 0]} user { /Type /Action /Subtype /Link /A
+ << /S /URI /URI (#2) >>}\BlueGreen #1\Black \pdfendlink
+ \else \ifpdf{\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#1}%
+ \special{pdf: ec}}\special{pdf: ann width \thewidth\space height \theheight
+ \space depth \thedepth\space << /Border [0 0 0]
+ /Type /Action /Subtype /Link /A << /S /URI /URI (#2) >> >>}\box0\relax}%
+ \else #1 ({\tt#2})\fi\fi}
+{\catcode`\~=12 \gdef\TILDE/{~}} % ~ in a URL
+{\catcode`\_=12 \gdef\UNDER/{_}} % _ in a URL
+\def\sanitizecommand#1#2{\addtokens\usersanitizer
+ {\noexpand\dosanitizecommand\noexpand#1{#2}}}
+\def\dosanitizecommand#1#2{\ifx\nxt#1\addF{#2}\fi}
+
+\catcode`\[=1 \catcode`\]=2 \catcode`\{=12 \catcode`\}=12
+ \def\lbchar[{] \def\rbchar[}]
+\catcode`\[=12 \catcode`\]=12 \catcode`\{=1 \catcode`\}=2
+\catcode`\~=12 \def\tildechar{~} \catcode`\~=13
+\catcode`\|=0 |catcode`|\=12 |def|bschar{\} |catcode`|\=0 \catcode`\|=12
+\def\makeoutlinetoks{\Tnumfalse\afterassignment\makeolproctok\let\nxt= }
+\def\makeolnexttok{\afterassignment\makeolproctok\let\nxt= }
+\def\makeolgobbletok{\afterassignment\makeolnexttok\let\nxt= }
+\def\addF#1{\addtokens\toksF{#1}\tokprocessedtrue}
+% now comes a routine to "sanitize" section names, for pdf outlines
+\def\makeolproctok{\tokprocessedfalse
+ \let\next\makeolnexttok % default
+ \ifx\nxt\outlinedone\let\next\outlinedone
+ \else\ifx{\nxt \else\ifx}\nxt \Tnumfalse \instrfalse % skip braces
+ \else\ifx$\nxt % or a $ sign
+ \else\ifx^\nxt \addF^\else\ifx_\nxt \addF_% sanitize ^ and _
+ \else\ifx\nxt\spacechar \addF\space
+ \else\if\noexpand\nxt\relax % we have a control sequence; is it one we know?
+ \ifx\nxt~\addF\space
+ \else\ifx\nxt\onespace\addF\space
+ \else\the\usersanitizer
+ \iftokprocessed\else\makeolproctokctli
+ \iftokprocessed\else\makeolproctokctlii
+ \iftokprocessed\else\makeolproctokctliii % if not recognised, skip it
+ \fi\fi\fi\fi\fi
+ \else % we don't have a control sequence, it's an ordinary char
+ \ifx/\nxt \addF{\string\/}% quote chars special to PDF with backslash
+ \else\ifx(\nxt \addF{\string\(}\else\ifx)\nxt \addF{\string\)}%
+ \else\ifx[\nxt \addF{\string\[}\else\ifx]\nxt \addF{\string\]}%
+ \else\expandafter\makeolproctokchar\meaning\nxt
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \next
+}
+\def\makeolproctokchar#1 #2 #3{\addF{#3}}
+\def\makeolproctokctli{%
+ \ifx\nxt\CEE\addF{C}\let\next\makeolgobbletok % \CEE/
+ \else\ifx\nxt\UNIX\addF{UNIX}\let\next\makeolgobbletok % \UNIX/
+ \else\ifx\nxt\TEX\addF{TeX}\let\next\makeolgobbletok % \TEX/
+ \else\ifx\nxt\TeX\addF{TeX}\else\ifx\nxt\LaTeX\addF{LaTeX}%
+ \else\ifx\nxt\CPLUSPLUS\addF{C++}\let\next\makeolgobbletok % \CPLUSPLUS/
+ \else\ifx\nxt\Cee\addF{C}%
+ \else\ifx\nxt\PB \let\next\makeolgobbletok \tokprocessedtrue % \PB{...}
+ \else\ifx\nxt\.\tokprocessedtrue\instrtrue % \.{...}
+ % skip \|
+ \else\ifx\nxt\\\ifinstr\addF{\bschar\bschar}\else\tokprocessedtrue\fi
+ \else\ifx\nxt\&\ifinstr\addF&\else\tokprocessedtrue\fi
+ \else\ifx\nxt\~\ifTnum\addF{0}\else\addF\tildechar\fi % 077->\T{\~77}
+ \else\ifx\nxt\_\ifTnum\addF{E}\else\addF_\fi % 0.1E5->\T{0.1\_5}
+ \else\ifx\nxt\^\ifTnum\addF{0x}\else\addF^\fi % 0x77 -> \T{\^77}
+ \else\ifx\nxt\$\ifTnum\tokprocessedtrue\else\addF$\fi % \T{77\$L}
+ \else\ifx\nxt\{\addF\lbchar \else\ifx\nxt\}\addF\rbchar
+ \else\ifx\nxt\ \addF\space \else\ifx\nxt\#\addF{\string\#}%
+ \else\ifx\nxt\PP\addF{++}\else\ifx\nxt\MM\addF{--}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+}
+\def\makeolproctokctlii{%
+ \ifx\nxt\MG\addF{->}\else\ifx\nxt\GG\addF{>>}%
+ \else\ifx\nxt\LL\addF{<<}\else\ifx\nxt\NULL\addF{NULL}%
+ \else\ifx\nxt\AND\addF&\else\ifx\nxt\OR\addF|%
+ \else\ifx\nxt\XOR\addF^\else\ifx\nxt\CM\addF\tildechar
+ \else\ifx\nxt\MOD\addF{\string\%}\else\ifx\nxt\DC\addF{::}%
+ \else\ifx\nxt\PA\addF{.*}\else\ifx\nxt\MGA\addF{->*}%
+ \else\ifx\nxt\this\addF{this}\else\ifx\nxt\?\addF?%
+ \else\ifx\nxt\E\addF{==}\else\ifx\nxt\G\addF{>=}%
+ \else\ifx\nxt\I\addF{!=}\else\ifx\nxt\K\addF{=}%
+ \else\ifx\nxt\l\addF{l}\else\ifx\nxt\L\addF{L}%
+ \else\ifx\nxt\o\addF{o}\else\ifx\nxt\O\addF{O}%
+ \else\ifx\nxt\R\addF!%
+ \else\ifx\nxt\T \Tnumtrue \let\next\makeolgobbletok
+ \tokprocessedtrue % \T{number}
+ \else\ifx\nxt\AM\addF&\else\ifx\nxt\%\addF{\string\%}%
+ \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
+ \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
+ \fi\fi\fi\fi\fi\fi
+}
+\def\makeolproctokctliii{%
+ \ifx\nxt\V\addF{||}\else\ifx\nxt\W\addF{&&}\else\ifx\nxt\Z\addF{<=}%
+ \else\ifx\nxt\*\addF*\else\ifx\nxt\Xand\addF{\space and\space}%
+ \else\ifx\nxt\Xandxeq\addF{\space and_eq\space}%
+ \else\ifx\nxt\Xbitand\addF{\space bitand\space}%
+ \else\ifx\nxt\Xbitor\addF{\space bitor\space}%
+ \else\ifx\nxt\Xcompl\addF{\space compl\space}%
+ \else\ifx\nxt\Xnot\addF{\space not\space}%
+ \else\ifx\nxt\Xnotxeq\addF{\space not_eq\space}%
+ \else\ifx\nxt\Xor\addF{\space or\space}%
+ \else\ifx\nxt\Xorxeq\addF{\space or_eq\space}%
+ \else\ifx\nxt\Xxor\addF{\space xor\space}%
+ \else\ifx\nxt\Xxorxeq\addF{\space xor_eq\space}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \fi\fi\fi\fi\fi
+}
+\def\outlinedone{\edef\outlinest{\global\noexpand\toksE={\the\toksF}}%
+ \outlinest\let\outlinedone=\relax}
+\fi % End of pdf macros
+
+\def\lapstar{\rlap{*}}
+\def\stsec{\rightskip=0pt % get out of C mode (cf. \B)
+ \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+ \noindent{\let\*=\lapstar\bf\secstar.\quad}%
+ \ifpdftex\smash{\raise\baselineskip\hbox to0pt{%
+ \let\*=\empty\pdfdest num \secstar fith}}
+ \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{%
+ \let\*=\empty\special{%
+ pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi}
+\let\startsection=\stsec
+\def\defin#1{\global\advance\ind by 2 \1\&{#1 } } % begin `define' or `format'
+\def\A{\note{See also section}} % xref for doubly defined section name
+\def\As{\note{See also sections}} % xref for multiply defined section name
+\def\B{\rightskip=0pt plus 100pt minus 10pt % go into C mode
+ \sfcode`;=3000
+ \pretolerance 10000
+ \hyphenpenalty 1000 % so strings can be broken (discretionary \ is inserted)
+ \exhyphenpenalty 10000
+ \global\ind=2 \1\ \unskip}
+\def\C#1{\5\5\quad$/\ast\,${\cmntfont #1}$\,\ast/$}
+\let\SHC\C % "// short comments" treated like "/* ordinary comments */"
+%\def\C#1{\5\5\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$}
+%\def\SHC#1{\5\5\quad$\diamond\,${\cmntfont#1}}
+\def\D{\defin{\#define}} % macro definition
+\let\E=\equiv % equivalence sign
+\def\ET{ and~} % conjunction between two section numbers
+\def\ETs{, and~} % conjunction between the last two of several section numbers
+\def\F{\defin{format}} % format definition
+\let\G=\ge % greater than or equal sign
+% \H is long Hungarian umlaut accent
+\let\I=\ne % unequal sign
+\def\J{\.{@\&}} % TANGLE's join operation
+\let\K== % assignment operator
+%\let\K=\leftarrow % "honest" alternative to standard assignment operator
+% \L is Polish letter suppressed-L
+\outer\def\M#1{\MN{#1}\ifon\vfil\penalty-100\vfilneg % beginning of section
+ \vskip\intersecskip\startsection\ignorespaces}
+\outer\def\N#1#2#3.{% beginning of starred section
+ \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi
+ \gdepth=#1\gtitle={#3}\MN{#2}%
+ \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small
+ \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi
+ \message{*\secno} % progress report
+ \def\stripprefix##1>{}\def\gtitletoks{#3}%
+ \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}%
+ \edef\next{\write\cont{\ZZ{\gtitletoks}{#1}{\secno}% write to contents file
+ {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss}
+ \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}
+ \ifnum#1>0\countB=#1 \advance\countB by-1
+ \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi
+ \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest
+ [ @thispage /FitH @ypos ] >>}\fi
+ \ifon\startsection{\bf#3.\quad}\ignorespaces}
+\def\MN#1{\par % common code for \M, \N
+ {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name
+ \ifx\secno\secstar \onmaybe \else\ontrue \fi
+ \mark{{{\tensy x}\secno}{\the\gdepth}{\the\gtitle}}}
+% each \mark is {section reference or null}{depth plus 1}{group title}
+% \O is Scandinavian letter O-with-slash
+% \P is paragraph sign
+\def\Q{\note{This code is cited in section}} % xref for mention of a section
+\def\Qs{\note{This code is cited in sections}} % xref for mentions of a section
+\let\R=\lnot % logical not
+% \S is section sign
+\def\T#1{\leavevmode % octal, hex or decimal constant
+ \hbox{$\def\?{\kern.2em}%
+ \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant
+ \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick)
+ \let\~=\oct \let\^=\hex {#1}$}}
+\def\U{\note{This code is used in section}} % xref for use of a section
+\def\Us{\note{This code is used in sections}} % xref for uses of a section
+\let\V=\lor % logical or
+\let\W=\land % logical and
+\def\X#1:#2\X{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi %$% section name
+ \XX$\langle\,${\let\I=\ne#2\eightrm\kern.5em
+ \ifacro{\pdfnote#1.}\else#1\fi}$\,\rangle$\XX}
+\def\Y{\par\yskip}
+\let\Z=\le
+\let\ZZ=\let % now you can \write the control sequence \ZZ
+\let\*=*
+
+\def\Xand{\W} \def\Xandxeq{\MRL{{\AND}{\K}}} \def\Xbitand{\AND}
+\def\Xbitor{\OR} \def\Xcompl{\CM} \def\Xnot{\R} \def\Xnotxeq{\I} \def\Xor{\V}
+\def\Xorxeq{\MRL{{\OR}{\K}}} \def\Xxor{\XOR} \def\Xxorxeq{\MRL{{\XOR}{\K}}}
+
+%\def\oct{\hbox{\rm\char'23\kern-.2em\it\aftergroup\?\aftergroup}} % WEB style
+%\def\hex{\hbox{\rm\char"7D\tt\aftergroup}} % WEB style
+\def\oct{\hbox{$^\circ$\kern-.1em\it\aftergroup\?\aftergroup}}% CWEB style
+\def\hex{\hbox{$^{\scriptscriptstyle\#}$\tt\aftergroup}} % CWEB style
+\def\vb#1{\leavevmode\hbox{\kern2pt\vrule\vtop{\vbox{\hrule
+ \hbox{\strut\kern2pt\.{#1}\kern2pt}}
+ \hrule}\vrule\kern2pt}} % verbatim string
+
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue
+\newif\ifon \newif\iftitle \newif\ifpagesaved
+
+\newif\ifheader
+\def\lheader{\headertrue\mainfont\the\pageno\eightrm\qquad\grouptitle
+ \hfill\title\qquad\mainfont\topsecno} % top line on left-hand pages
+\def\rheader{\headertrue\mainfont\topsecno\eightrm\qquad\title\hfill
+ \grouptitle\qquad\mainfont\the\pageno} % top line on right-hand pages
+\def\grouptitle{\let\i=I\let\j=J\uppercase\expandafter{\expandafter
+ \takethree\topmark}}
+\def\topsecno{\expandafter\takeone\topmark}
+\def\takeone#1#2#3{#1}
+\def\taketwo#1#2#3{#2}
+\def\takethree#1#2#3{#3}
+\def\nullsec{\eightrm\kern-2em} % the \kern-2em cancels \qquad in headers
+
+\let\page=\pagebody \raggedbottom
+% \def\page{\box255 }\normalbottom % faster, but loses plain TeX footnotes
+\def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi
+ \shipout\vbox{
+ \vbox to\fullpageheight{
+ \iftitle\global\titlefalse
+ \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi
+ \vfill#1}} % parameter #1 is the page itself
+ \global\advance\pageno by1}
+
+\gtitle={\.{CWEB} output} % this running head is reset by starred sections
+\mark{\noexpand\nullsec0{\the\gtitle}}
+\def\title{\expandafter\uppercase\expandafter{\jobname}}
+\def\topofcontents{\centerline{\titlefont\title}\vskip.7in
+ \vfill} % this material will start the table of contents page
+\def\startpdf{\ifpdftex\pdfcatalog{/PageMode /UseOutlines}\else
+ \ifpdf{\special{pdf: docview << /PageMode /UseOutlines >>}}\fi\fi}
+\def\botofcontents{\vfill
+ \centerline{\covernote}} % this material will end the table of contents page
+\def\covernote{}
+\def\contentspagenumber{0} % default page number for table of contents
+\newdimen\pagewidth \pagewidth=6.5in % the width of each page
+\newdimen\pageheight \pageheight=8.7in % the height of each page
+\newdimen\fullpageheight \fullpageheight=9in % page height including headlines
+\newdimen\pageshift \pageshift=0in % shift righthand pages wrt lefthand ones
+\def\magnify#1{\mag=#1\pagewidth=6.5truein\pageheight=8.7truein
+ \fullpageheight=9truein\setpage}
+\def\setpage{\hsize\pagewidth\vsize\pageheight} % use after changing page size
+\def\contentsfile{\jobname.toc} % file that gets table of contents info
+\def\readcontents{\input \contentsfile}
+\def\readindex{\input \jobname.idx}
+\def\readsections{\input \jobname.scn}
+
+\newwrite\cont
+\output{\setbox0=\page % the first page is garbage
+ \openout\cont=\contentsfile
+ \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+ \global\output{\normaloutput\page\lheader\rheader}}
+\setpage
+\vbox to \vsize{} % the first \topmark won't be null
+
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+\newbox\sbox % saved box preceding the index
+\newbox\lbox % lefthand column in the index
+\def\inx{\par\vskip6pt plus 1fil % we are beginning the index
+ \def\page{\box255 } \normalbottom
+ \write\cont{} % ensure that the contents file isn't empty
+ \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother
+ \closeout\cont % the contents information has been fully gathered
+ \output{\ifpagesaved\normaloutput{\box\sbox}\lheader\rheader\fi
+ \global\setbox\sbox=\page \global\pagesavedtrue}
+ \pagesavedfalse \eject % eject the page-so-far and predecessors
+ \setbox\sbox\vbox{\unvbox\sbox} % take it out of its box
+ \vsize=\pageheight \advance\vsize by -\ht\sbox % the remaining height
+ \hsize=.5\pagewidth \advance\hsize by -10pt
+ % column width for the index (20pt between cols)
+ \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+ \def\lr{L} % this tells whether the left or right column is next
+ \output{\if L\lr\global\setbox\lbox=\page \gdef\lr{R}
+ \else\normaloutput{\vbox to\pageheight{\box\sbox\vss
+ \hbox to\pagewidth{\box\lbox\hfil\page}}}\lheader\rheader
+ \global\vsize\pageheight\gdef\lr{L}\global\pagesavedfalse\fi}
+ \message{Index:}
+ \parskip 0pt plus .5pt
+ \outer\def\I##1, ##2.{\par\hangindent2em\noindent##1:\kern1em
+ \ifacro\pdfnote##2.\else##2\fi.} % index entry
+ \def\[##1]{$\underline{##1}$} % underlined index item
+ \rm \rightskip0pt plus 2.5em \tolerance 10000 \let\*=\lapstar
+ \hyphenpenalty 10000 \parindent0pt
+ \readindex}
+\def\fin{\par\vfill\eject % this is done when we are ending the index
+ \ifpagesaved\null\vfill\eject\fi % output a null index column
+ \if L\lr\else\null\vfill\eject\fi % finish the current page
+ \parfillskip 0pt plus 1fil
+ \def\grouptitle{NAMES OF THE SECTIONS}
+ \let\topsecno=\nullsec
+ \message{Section names:}
+ \output={\normaloutput\page\lheader\rheader}
+ \setpage
+ \def\note##1##2.{\quad{\eightrm##1~\ifacro{\pdfnote##2.}\else{##2}\fi.}}
+ \def\Q{\note{Cited in section}} % crossref for mention of a section
+ \def\Qs{\note{Cited in sections}} % crossref for mentions of a section
+ \def\U{\note{Used in section}} % crossref for use of a section
+ \def\Us{\note{Used in sections}} % crossref for uses of a section
+ \def\I{\par\hangindent 2em}\let\*=*
+ \ifacro \def\outsecname{Names of the sections} \let\Xpdf\X
+ \ifpdftex \makebookmarks \pdfdest name {NOS} fitb
+ \pdfoutline goto name {NOS} count -\secno {\outsecname}
+ \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.%
+ {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}%
+ \pdfoutline goto num \the\toksA \expandafter{\the\toksE}}
+ \else\ifpdf
+ \special{pdf: outline -1 << /Title (\outsecname)
+ /Dest [ @thispage /FitH @ypos ] >>}
+ \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.%
+ {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}%
+ \special{pdf: outline 0 << /Title (\the\toksE)
+ /A << /S /GoTo /D (\romannumeral\the\toksA) >> >>}}
+ \fi\fi\fi
+ \readsections}
+\def\makebookmarks{\let\ZZ=\writebookmarkline \readcontents\relax}
+\def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+ \else \csname#1\endcsname \fi} % Petr Olsak's macros from texinfo.tex
+\def\advancenumber#1{\countA=\expnumber{#1}\relax \advance\countA by1
+ \expandafter\xdef\csname#1\endcsname{\the\countA}}
+\def\writebookmarkline#1#2#3#4#5{{%
+ \let\(=\let \let\)=\let \let\[=\let \let\]=\let \let\/=\let
+ \pdfoutline goto num #3 count -\expnumber{chunk#2.#3} {#5}}}
+\def\con{\par\vfill\eject % finish the section names
+% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+ \rightskip 0pt \hyphenpenalty 50 \tolerance 200
+ \setpage \output={\normaloutput\page\lheader\rheader}
+ \titletrue % prepare to output the table of contents
+ \pageno=\contentspagenumber
+ \def\grouptitle{TABLE OF CONTENTS}
+ \message{Table of contents:}
+ \topofcontents \startpdf
+ \line{\hfil Section\hbox to3em{\hss Page}}
+ \let\ZZ=\contentsline
+ \readcontents\relax % read the contents info
+ \botofcontents \end} % print the contents page(s) and terminate
+\def\contentsline#1#2#3#4#5{\ifnum#2=0 \smallbreak\fi
+ \line{\consetup{#2}#1
+ \rm\leaders\hbox to .5em{.\hfil}\hfil
+ \ \ifacro\pdflink{#3}{\romannumeral#3}\else#3\fi\hbox to3em{\hss#4}}}
+\def\consetup#1{\ifcase#1 \bf % depth -1 (@**)
+ \or % depth 0 (@*)
+ \or \hskip2em % depth 1 (@*1)
+ \or \hskip4em \or \hskip6em \or \hskip8em \or \hskip10em % depth 2,3,4,5
+ \else \hskip12em \fi} % depth 6 or more
+\def\noinx{\let\inx=\end} % no indexes or table of contents
+\def\nosecs{\let\FIN=\fin \def\fin{\let\parfillskip=\end \FIN}}
+ % no index of section names or table of contents
+\def\nocon{\let\con=\end} % no table of contents
+\def\today{\ifcase\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December\fi
+ \space\number\day, \number\year}
+\newcount\twodigits
+\def\hours{\twodigits=\time \divide\twodigits by 60 \printtwodigits
+ \multiply\twodigits by-60 \advance\twodigits by\time :\printtwodigits}
+\def\gobbleone1{}
+\def\printtwodigits{\advance\twodigits100
+ \expandafter\gobbleone\number\twodigits
+ \advance\twodigits-100 }
+\def\TeX{{\ifmmode\it\fi
+ \leavevmode\hbox{T\kern-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}}
+\def\,{\relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+\def\datethis{\def\startsection{\leftline{\sc\today\ at \hours}\bigskip
+ \let\startsection=\stsec\stsec}}
+ % say `\datethis' in limbo, to get your listing timestamped before section 1
+\def\datecontentspage{%
+ \def\topofcontents{\leftline{\sc\today\ at \hours}\bigskip
+ \centerline{\titlefont\title}\vfill}} % timestamps the contents page
diff --git a/Build/source/texk/web2c/cwebdir/cwebman.tex b/Build/source/texk/web2c/cwebdir/cwebman.tex
new file mode 100644
index 00000000000..49f43531d8c
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/cwebman.tex
@@ -0,0 +1,1761 @@
+% This file generates the user manual; TeX it, don't read it!
+
+\def\tangref{3} % where the main explanation of CTANGLing is given
+\input cwebmac
+\acrofalse\pdffalse\pdftexfalse
+\def\page{\box255 } \normalbottom
+\parskip 0pt plus 1pt
+\def\RA{\char'31 } % right arrow
+\def\hang{\hangindent 4em\ignorespaces}
+\font\eightrm=cmr8
+\font\ninerm=cmr9
+\font\ninett=cmtt9
+\font\eighttt=cmtt8
+\font\twelvett=cmtt12
+\font\quoterm=cmssq8
+\font\quoteit=cmssqi8
+\font\authorfont=cmr12
+\font\sectionfont=cmbx12
+
+\def\pb{\.{|...|}}
+\def\v{\.{\char'174}} % vertical (|) in typewriter font
+\def\lpile{\def\cr{\hfill\endline}\matrix} % I only use \lpile by itself
+\abovedisplayskip=.5\abovedisplayskip
+\belowdisplayskip=.5\belowdisplayskip
+\abovedisplayshortskip=.5\abovedisplayshortskip
+\belowdisplayshortskip=.5\belowdisplayshortskip
+\advance\baselineskip by -.5pt
+\advance\pageheight by \baselineskip % the manual just got a bit longer
+\advance\fullpageheight by \baselineskip
+\setpage
+
+\outer\def\section #1.{\penalty-500\bigskip
+ \centerline{\sectionfont\def\.##1{{\twelvett##1}} #1}\nobreak\vskip 6pt
+ \everypar{\hskip-\parindent\everypar{}}}
+
+\def\lheader{\mainfont\the\pageno\hfill\sc\runninghead\hfill}
+\def\rheader{\hfill\sc\runninghead\hfill\mainfont\the\pageno}
+\def\runninghead{{\tentt CWEB} USER MANUAL (VERSION 3.64)}
+
+% This verbatim mode assumes that ! marks are !! in the text being copied.
+\def\verbatim{\begingroup
+ \def\do##1{\catcode`##1=12 } \dospecials
+ \parskip 0pt \parindent 0pt \let\!=!
+ \catcode`\ =13 \catcode`\^^M=13
+ \tt \catcode`\!=0 \verbatimdefs \verbatimgobble}
+{\catcode`\^^M=13{\catcode`\ =13\gdef\verbatimdefs{\def^^M{\ \par}\let =\ }} %
+ \gdef\verbatimgobble#1^^M{}}
+
+\null\vfill
+\centerline{\titlefont The {\ttitlefont CWEB} System of
+ Structured Documentation}
+\vskip 18pt\centerline{(Version 3.64 --- February 2002)}
+\vskip 24pt
+\centerline{\authorfont Donald E. Knuth and Silvio Levy}
+\vfill
+
+\noindent
+\TeX\ is a trademark of the American Mathematical Society.
+
+\noindent
+Acrobat Reader is a trademark of Adobe Systems Incorporated.
+
+\bigskip\noindent
+The printed form of this manual is copyright \copyright\ 1994
+ by Addison-Wesley Publishing Company, Inc. All rights reserved.
+\smallskip\noindent
+The electronic form is copyright \copyright\ 1987, 1990, 1993, 2000
+ by Silvio Levy and Donald E. Knuth.
+
+\bigskip\noindent
+Permission is granted to make and distribute verbatim copies of the
+electronic form of this document provided that the electronic copyright
+notice and this permission notice are preserved on all copies.
+
+\smallskip\noindent
+Permission is granted to copy and distribute modified versions of the
+electronic form of this document under the conditions for verbatim copying,
+provided that the entire resulting derived work is distributed under the terms
+of a permission notice identical to this one.
+
+\smallskip\noindent
+Individuals may make copies of the documentation from the electronic files
+for their own personal use.
+
+\smallskip\noindent
+Internet page \.{http://www-cs-faculty.stanford.edu/\char`\~knuth/cweb.html}
+contains current info about \.{CWEB} and related topics.
+
+\pageno=0 \titletrue\eject
+
+\titletrue
+\centerline{\titlefont The {\ttitlefont CWEB} System of
+ Structured Documentation}
+
+\vskip 15pt plus 3pt minus 3pt
+\centerline{\authorfont Donald E. Knuth and Silvio Levy}
+
+\vskip 24pt plus 3pt minus 3pt
+\noindent
+This document describes a version of Don Knuth's \.{WEB} system,
+adapted to \CEE/ by Silvio Levy. Since its creation in 1987, \.{CWEB}
+has been revised and enhanced in various ways, by both Knuth and Levy.
+We now believe that its evolution is near an end; however, bug
+reports, suggestions and comments are still welcome, and
+should be sent to Levy (\.{levy@math.berkeley.edu}).
+
+Readers who are familiar with Knuth's memo ``The \.{WEB} System of Structured
+Documentation'' will be able
+to skim this material rapidly, because \.{CWEB} and \.{WEB} share
+the same philosophy and (essentially) the same syntax. In some respects
+\.{CWEB} is a simplification
+of \.{WEB}: for example, \.{CWEB} does not need \.{WEB}'s features
+for macro definition and string handling, because \CEE/ and its
+preprocessor already take care of macros and strings. Similarly, the \.{WEB}
+conventions of denoting octal and hexadecimal constants by \.{@'77}
+and \.{@"3f} are replaced by \CEE/'s conventions \.{077} and
+\.{0x3f}. All other features of \.{WEB} have been
+retained, and new features have been added.
+
+We thank all who contributed suggestions and criticism to
+the development of \.{CWEB}. We are especially grateful to Steve
+Avery, Nelson Beebe, Hans-Hermann Bode, Klaus Guntermann, Norman Ramsey,
+Joachim Schnitter, and Saroj Mahapatra,
+who contributed code, and to Cameron Smith, who
+made many suggestions improving the manual. Ramsey has made
+literate programming accessible to users of yet other languages by means of
+his \.{SPIDER} system [see {\sl Communications of the ACM\/ \bf32} (1989),
+1051--1055]. The book {\sl Literate Programming\/} by Knuth (1992) contains
+a comprehensive bibliography of related early work.
+Bode, Schnitter, and Mahapatra adapted \.{CWEB} so that it works
+for \CPLUSPLUS/ as well; therefore in the text below you can read \CPLUSPLUS/
+for \CEE/ if you so desire.
+
+\section Introduction.
+The philosophy behind \.{CWEB} is
+that programmers who want to provide the best
+possible documentation for their programs need two things
+simultaneously: a language like \TEX/ for formatting, and a language like
+\CEE/ for programming. Neither type of language can provide the
+best documentation by itself. But when both are appropriately combined, we
+obtain a system that is much more useful than either language separately.
+
+The structure of a software program may be thought of as a ``web'' that is
+made up of many interconnected pieces. To document such a program, we want
+to explain each individual part of the web and how it relates to its
+neighbors. The typographic tools provided by \TEX/ give us an opportunity
+to explain the local structure of each part by making that structure
+visible, and the programming tools provided by \CEE/ make it possible
+for us to specify the algorithms formally and unambiguously. By combining
+the two, we can develop a style of programming that maximizes our ability
+to perceive the structure of a complex piece of software, and at the same
+time the documented programs can be mechanically translated into a working
+software system that matches the documentation.
+
+The \.{CWEB} system consists of two programs named \.{CWEAVE} and \.{CTANGLE}.
+When writing a \.{CWEB} program the user keeps the
+\CEE/ code and the documentation in the same file, called the \.{CWEB}
+file and generally named \.{something.w}. The command
+`\.{cweave} \.{something}' creates an output file \.{something.tex}, which
+can then be fed to \TEX/, yielding a ``pretty printed'' version of
+\.{something.w} that correctly handles
+typographic details like page layout and the use of indentation,
+italics, boldface, and mathematical symbols. The typeset output also
+includes extensive cross-index
+information that is gathered automatically. Similarly, if you run the
+command `\.{ctangle} \.{something}' you will get a \CEE/ file \.{something.c},
+which can then be compiled to yield executable code.
+
+Besides providing a documentation tool, \.{CWEB} enhances the \CEE/
+language by providing the
+ability to permute pieces of the program text, so that a large system can
+be understood entirely in terms of small sections and their local
+interrelationships. The \.{CTANGLE} program is so named because it takes a
+given web and moves the sections from their web structure into the order
+required by \CEE/; the advantage of programming in \.{CWEB} is that the
+algorithms can be expressed in ``untangled'' form, with each section
+explained separately. The \.{CWEAVE} program is so named because it takes
+a given web and intertwines the \TEX/ and \CEE/ portions contained in
+each section, then it knits the whole fabric into a structured document.
+(Get it? Wow.) Perhaps there is some deep connection here with the fact
+that the German word for ``weave'' is ``{\it webe\/}'', and the
+corresponding Latin imperative is ``{\it texe\/}''!
+
+A user of \.{CWEB} should be fairly familiar with the \CEE/
+programming language. A minimal amount of acquaintance with \TEX/ is also
+desirable, but in fact it can be acquired as one uses \.{CWEB}, since
+straight text can be typeset in \TEX/ with virtually no knowledge of
+that language. To someone familiar with both \CEE/ and \TEX/ the amount of
+effort necessary to learn the commands of \.{CWEB} is small.
+
+\section Overview.
+Two kinds of material go into \.{CWEB} files: \TEX/ text and \CEE/ text.
+A programmer writing in \.{CWEB} should be thinking both of the
+documentation and of the \CEE/ program being created;
+i.e., the programmer should be instinctively aware of the different
+actions that \.{CWEAVE} and \.{CTANGLE} will perform on the \.{CWEB} file.
+\TEX/ text is essentially copied without change by \.{CWEAVE}, and it is
+entirely deleted by \.{CTANGLE}; the \TEX/ text is ``pure
+documentation.'' \CEE/ text, on the other hand, is formatted by
+\.{CWEAVE} and it is shuffled around by \.{CTANGLE}, according to rules that
+will become clear later. For now the important point to keep in mind is
+that there are two kinds of text. Writing \.{CWEB} programs is something
+like writing \TEX/ documents, but with an additional ``\CEE/ mode''
+that is added to \TEX/'s horizontal mode, vertical mode, and math mode.
+
+A \.{CWEB} file is built up from units called {\sl sections\/} that are more
+or less self-contained. Each section has three parts:
+
+\yskip\item{$\bullet$} A \TEX/ part, containing explanatory material about what
+is going on in the section.
+
+\item{$\bullet$} A middle part, containing macro definitions that serve as
+abbreviations for \CEE/ constructions that would be less comprehensible
+if written out in full each time. They are turned by \.{CTANGLE} into
+preprocessor macro definitions.
+
+\item{$\bullet$} A \CEE/ part, containing a piece of the program that
+\.{CTANGLE} will produce. This \CEE/ code should ideally be about a
+dozen lines long, so that it is easily comprehensible as a unit and so
+that its structure is readily perceived.
+
+\yskip\noindent The three parts of each section must appear in this order;
+i.e., the \TEX/ commentary must come first, then the middle part, and
+finally the \CEE/ code. Any of the parts may be empty.
+
+A section begins with either of the symbols `\.{@\ }' or `\.{@*}', where
+`\.{\ }' denotes a blank space. A section ends
+at the beginning of the next section (i.e., at the next
+`\.{@\ }' or `\.{@*}'), or at the end of the file, whichever comes first.
+The \.{CWEB} file may also contain material that is not part of any section
+at all, namely the text (if any) that occurs before the first section.
+Such text is said to be ``in limbo''; it is ignored by \.{CTANGLE}
+and copied essentially verbatim by \.{CWEAVE}, so its function is to
+provide any additional formatting instructions that may be desired in the
+\TEX/ output. Indeed, it is customary to begin a \.{CWEB} file with
+\TEX/ code in limbo that loads special fonts, defines special macros,
+changes the page sizes, and/or produces a title page.
+
+Sections are numbered consecutively, starting with 1. These numbers appear
+at the beginning of each section of the \TEX/ documentation output by
+\.{CWEAVE}, and they appear
+as bracketed comments at the beginning and end of the code generated by that
+section in the \CEE/ program output by \.{CTANGLE}.
+
+\section Section Names.
+Fortunately, you never mention these numbers yourself when you are writing
+in \.{CWEB}. You just say `\.{@\ }' or `\.{@*}' at the beginning of each
+new section, and the numbers are supplied automatically by \.{CWEAVE} and
+\.{CTANGLE}. As far as you are concerned, a section has a
+{\sl name\/} instead of a number; its name is specified by writing
+`\.{@<}' followed by \TEX/ text followed by `\.{@>}'. When \.{CWEAVE}
+outputs a section name, it replaces the `\.{@<}' and `\.{@>}' by
+angle brackets and inserts the section number in small type. Thus, when you
+read the output of \.{CWEAVE} it is easy to locate any section that is
+referred to in another section.
+
+For expository purposes, a section name should be a good description of the
+contents of that section; i.e., it should stand for the abstraction
+represented by the section. Then the section can be ``plugged into'' one or
+more other sections in such a way
+that unimportant details of its inner workings
+are suppressed. A section name therefore ought to be long enough to convey
+the necessary meaning.
+
+Unfortunately, it is laborious to type
+such long names over and over again, and it is also difficult to specify a
+long name twice in exactly the same way so that \.{CWEAVE} and \.{CTANGLE}
+will be able to match the names to the sections. To ameliorate this situation,
+\.{CWEAVE} and \.{CTANGLE} let you abbreviate a section name, so long as
+the full name appears somewhere in the \.{CWEB} file; you can type simply
+`\.{@<$\alpha$...@>}', where $\alpha$ is any string that is a prefix of
+exactly one section name appearing in the file. For example, `\.{@<Clear
+the arrays@>}' can be abbreviated to `\.{@<Clear...@>}' if no other section
+name begins with the five letters `\.{Clear}'. Elsewhere
+you might use the abbreviation `\.{@<Clear t...@>}', and so on.
+
+Section names must otherwise match character for character, except
+that consecutive characters of white space (spaces, tab marks, newlines, and/or
+form feeds) are treated as equivalent to a single space, and such spaces are
+deleted at the beginning and end of the name. Thus, `\.{@< Clear { }the
+arrays @>}' will also match the name in the previous example.
+Spaces following the ellipsis in abbreviations are ignored as well, but
+not those before, so that `\.{@<Clear t ...@>}' would not match
+`\.{@<Clear the arrays@>}'.
+
+\section What \.{CTANGLE} Does.
+We have said that a section begins with `\.{@\ }' or `\.{@*}', but we
+didn't say how it gets divided up into a \TEX/ part, a middle part,
+and a \CEE/ part. The middle part begins with the first appearance of
+`\.{@d}' or `\.{@f}' in the section, and the \CEE/ part begins with
+the first appearance of `\.{@c}' or `\.{@<section name@>=}'. In the
+latter case you are saying, in effect, that the section name stands
+for the \CEE/ text that follows. Alternatively, if the \CEE/ part
+begins with `\.{@c}' instead of a section name, the current section is
+said to be {\sl unnamed}.
+
+The construct `\.{@<section name@>}' can appear
+any number of times in the \CEE/ part of a section:
+Subsequent appearances indicate that a named section is being
+``used'' rather than ``defined.'' In other words, the
+\CEE/ code for the named section, presumably defined elsewhere, should be
+spliced in at this point in the \CEE/ program. Indeed,
+the main idea of \.{CTANGLE} is to make a \CEE/ program out of
+individual sections, named and unnamed. The exact way in which this is done
+is this: First all the macro definitions
+indicated by `\.{@d}' are turned into \CEE/ preprocessor macro definitions
+and copied at the beginning.
+Then the \CEE/ parts of unnamed sections are copied down,
+in order; this constitutes the first-order
+approximation to the text of the program. (There should be at least
+one unnamed section, otherwise there will be no program.) Then all section
+names that appear in the first-order approximation are replaced by the \CEE/
+parts of the corresponding sections, and this substitution process
+continues until no section names remain. All comments are removed, because
+the \CEE/ program is intended only for the eyes of the \CEE/ compiler.
+
+If the same name has been given to more than one section, the \CEE/ text
+for that name is obtained by putting together all of the \CEE/ parts in
+the corresponding sections. This feature is useful, for example, in a
+section named `Global variables', since one can then
+declare global variables in whatever sections those variables are
+introduced. When several sections have the same name, \.{CWEAVE} assigns the
+first section number as the number corresponding to that name, and it
+inserts a note at the bottom of that section telling the reader to `See
+also sections so-and-so'; this footnote gives the numbers of all the other
+sections having the same name as the present one. The \CEE/ text
+corresponding to a section is usually formatted by \.{CWEAVE} so that the
+output has an equivalence sign in place of the equals sign in the \.{CWEB}
+file; i.e., the output says `$\langle\,$section
+name$\,\rangle\equiv\null$\CEE/ text'. However, in the case of the second
+and subsequent appearances of a section with the same name, this `$\equiv$'
+sign is replaced by `$\mathrel+\equiv$', as an indication that the
+following \CEE/ text is being appended to the \CEE/ text of another section.
+
+As \.{CTANGLE} enters and leaves sections, it inserts preprocessor
+\.{\#line} commands into the \CEE/ output file. This means that
+when the compiler gives you error messages, or when you debug your program,
+the messages refer to line numbers in the \.{CWEB} file, and not in the
+\CEE/ file. In most cases you can therefore
+forget about the \CEE/ file altogether.
+
+\section What \.{CWEAVE} Does.
+The general idea of \.{CWEAVE} is to make a \.{.tex} file from the \.{CWEB}
+file in the following way: The first line of the \.{.tex} file
+tells \TEX/ to input a file with macros that
+define \.{CWEB}'s documentation conventions. The next lines of the file
+will be copied from whatever \TEX/ text is in limbo before the first
+section. Then comes the output for each section in turn, possibly
+interspersed with end-of-page marks. Finally, \.{CWEAVE} will generate a
+cross-reference index that lists each section number in which each \CEE/
+identifier appears, and it will also generate an alphabetized list
+of the section names, as well as a table of contents that
+shows the page and section numbers for each ``starred'' section.
+
+What is a ``starred'' section, you ask? A section that begins with `\.{@*}'
+instead of `\.{@\ }' is slightly special in that it denotes a new major
+group of sections. The `\.{@*}' should be followed by the title of this
+group, followed by a period. Such sections will always start on a new page
+in the \TEX/ output, and the group title will appear as a running headline
+on all subsequent pages until the next starred section. The title will also
+appear in the table of contents, and in boldface type at the beginning of
+its section. Caution: Do not use \TEX/ control sequences in such titles,
+unless you know that the \.{cwebmac} macros will do the right thing with
+them. The reason is that these titles are converted to uppercase when
+they appear as running heads, and they are converted to boldface when they
+appear at the beginning of their sections, and they are also written out to
+a table-of-contents file used for temporary storage while \TEX/ is
+working; whatever control sequences you use must be meaningful in all
+three of these modes.
+
+The \TEX/ output produced by \.{CWEAVE} for each section consists of
+the following: First comes the section number (e.g., `\.{\\M123.}'
+at the beginning of section 123, except that `\.{\\N}' appears in place of
+`\.{\\M}' at the beginning of a starred section). Then comes the
+\TEX/ part of the section, copied almost verbatim except as noted
+below. Then comes the middle part and the \CEE/ part, formatted
+so that there will be a little extra space between them if both are
+nonempty. The middle and \CEE/ parts are obtained by inserting
+a bunch of funny-looking \TEX/ macros into the \CEE/ program; these
+macros handle typographic details about fonts and proper math spacing,
+as well as line breaks and indentation.
+
+\section C Code in \TEX/ Text and Vice Versa.
+When you are typing \TEX/ text, you will probably want to make frequent
+reference to variables and other quantities in your \CEE/ code, and you
+will want those variables to have the same typographic treatment
+when they appear in your text as when they appear in your
+program. Therefore the \.{CWEB} language allows you to get the effect of
+\CEE/ editing within \TEX/ text, if you place `\.|' marks before and
+after the \CEE/ material. For example, suppose you want to say something
+like this:
+$$\hbox{ If \\{pa} is declared as `\&{int} ${}{*}\\{pa}$',
+the assignment $\\{pa}\K{\AND}\|a[\T{0}]$ makes \\{pa}
+point to the zeroth element of \|a.}$$
+The \TEX/ text would look like this in your \.{CWEB} file:
+$$\lpile{\.{If |pa| is declared as `|int *pa|', the}\cr
+\.{assignment |pa=\&a[0]| makes |pa| point
+to the zeroth element of |a|.}\cr}$$
+And \.{CWEAVE} translates this into something you are glad you didn't have
+to type:
+$$\lpile{\.{If \\\\\{pa\} is declared as
+ `\\\&\{int\} \$\{\}\{*\}\\\\\{pa\}\$',}\cr
+\.{the assignment \$\\\\\{pa\}\\K\{\\AND\}\\|a[\\T\{0\}]\$}\cr
+\.{makes \\\\\{pa\} point to the zeroth element of \\|a.}\cr}$$
+Incidentally, the cross-reference index that \.{CWEAVE} would make, in
+the presence of a comment like this, would include
+the current section number as one of the index entries for \\{pa},
+even though \\{pa} might not appear in the \CEE/ part of
+this section. Thus, the index covers references to identifiers in
+the explanatory comments as well as in the program itself; you will
+soon learn to appreciate this feature. However, the identifiers
+\&{int} and \|a\ would not be indexed,
+because \.{CWEAVE} does not make index entries for reserved words or
+single-letter identifiers. Such identifiers are felt to be so ubiquitous
+that it would be pointless to mention every place where they occur.
+
+Although a section begins with \TEX/ text and ends with \CEE/ text, we
+have noted that the dividing line isn't sharp, since \CEE/ text can be
+included in \TEX/ text if it is enclosed in `\pb'. Conversely, \TEX/ text
+appears frequently within \CEE/ text, because everything in
+comments (i.e., between \.{/*} and \.{*/}, or following \.{//})
+is treated as \TEX/ text.
+Likewise, the text of a section name consists of \TEX/ text, but
+the construct \.{@<section name@>} as a whole is expected to be found
+in \CEE/ text; thus, one typically goes back and forth
+between the \CEE/ and \TEX/ environments in a natural way, as in these
+examples:
+$$
+\displaylines{
+\hbox{\.{if} \.{(x==0)} \.{@<Empty} \.{the} \.{|buffer|} \.{array@>}} \cr
+\hbox{\.{...} \.{using} \.{the} \.{algorithm}
+\.{in} \.{|@<Empty} \.{the} \.{|buffer|} \.{array@>|.}} }
+$$
+The first of these excerpts
+would be found in the \CEE/ part of a section, into which the code
+from the section
+named ``Empty the \\{buffer} array'' is being spliced. The second excerpt
+would be found in the \TEX/ part of the section, and the named section
+is being ``cited'', rather than defined or used.
+(Note the `\pb' surrounding the section name in this case.)
+
+\section Macros.
+The control code \.{@d} followed by
+$$\\{identifier}\.{ }\hbox{\CEE/ text}\qquad\hbox{or by}\qquad
+\\{identifier}\.(\\{par}_1,\ldots,\\{par}_n\.{) }\hbox{\CEE/ text}$$
+(where there is no blank between the
+\\{identifier} and the parentheses in the second case) is
+transformed by \.{CTANGLE} into a preprocessor command, starting with
+\.{\#define}, which is printed at the top of the \CEE/ output file
+as explained earlier.
+
+A `\.{@d}' macro definition can go on for several lines, and the
+newlines don't have to be protected by backslashes, since \.{CTANGLE}
+itself inserts the backslashes. If
+for any reason you need a \.{\#define} command at a specific spot in
+your \CEE/ file, you can treat it as \CEE/ code, instead of as a
+\.{CWEB} macro; but then you do have to protect newlines yourself.
+
+\section Strings and constants.
+If you want a string to appear in the \CEE/ file, delimited by pairs of
+\.' or \." marks as usual, you can type it exactly so in the \.{CWEB} file,
+except that the character `\.@' should be typed `\.{@@}' (it becomes a
+control code, the only one that can appear in strings; see below).
+Strings should end on the same line as they begin, unless there's a
+backslash at the end of lines within them.
+
+\TEX/ and \CEE/ have different ways to refer to octal and hex constants,
+because \TEX/ is oriented to technical writing while \CEE/ is oriented to
+computer processing. In \TEX/ you
+make a constant octal or hexadecimal by prepending \.' or \.",
+respectively, to it; in \CEE/ the constant should be preceded by \.0
+or \.{0x}. In \.{CWEB} it seems reasonable to let each convention hold
+in its respective realm; so in \CEE/ text you get $40_8$ by typing
+`\.{040}', which \.{CTANGLE} faithfully copies into the \CEE/ file (for
+the compiler's benefit) and which \.{CWEAVE} prints as $\T{\~40}$.
+Similarly, \.{CWEAVE} prints the hexadecimal \CEE/ constant `\.{0x20}'
+as \T{\^20}. The use of italic font for octal digits and typewriter font
+for hexadecimal digits makes the meaning of such constants clearer in
+a document. For consistency, then, you
+should type `\.{|040|}' or `\.{|0x20|}'
+in the \TEX/ part of the section.
+
+\section Control codes.
+A \.{CWEB} {\sl control code\/}
+is a two-character combination of which the first is `\.@'.
+We've already seen the meaning of several control codes; it's time to
+list them more methodically.
+
+In the following list,
+the letters in brackets after a control code indicate in what contexts that
+code is allowed. $L$ indicates that the code is allowed in limbo; $T$
+(for \TEX/), $M$ (for middle), and $C$ (for \CEE/) mean that the code is
+allowed in each of the three parts of a section, at top level---that
+is, outside such constructs as `\pb' and section names. An arrow $\to$
+means that the control code terminates the present part of the \.{CWEB}
+file, and inaugurates the part indicated by the letter following the
+arrow. Thus $[LTMC\to T]$ next to \.{@\ } indicates that this control
+code can occur in limbo, or in any of the three parts of a section, and
+that it starts the (possibly empty) \TEX/ part of the following section.
+
+Two other abbreviations can occur in these brackets: The letter $r$ stands for
+{\it restricted context}, that is, material inside \CEE/ comments, section
+names, \CEE/ strings and control texts (defined below); the letter
+$c$ stands for {\it inner \CEE/ context}, that is, \CEE/ material
+inside `\pb' (including `\pb's inside comments, but not those
+occurring in other restricted contexts). An asterisk $*$ following
+the brackets means
+that the context from this control code to the matching \.{@>} is
+restricted.
+
+Control codes involving letters are case-insensitive; thus \.{@d} and
+\.{@D} are equivalent. Only the lowercase versions are mentioned
+specifically below.
+
+\gdef\@#1[#2] {\penalty-50\yskip\hangindent 2em\noindent\.{@#1\unskip
+ \spacefactor1000{ }}$[#2]$\quad}
+\def\more{\hangindent 2em \hangafter0}
+\def\subsec{\penalty-300\medskip\noindent}
+
+\@@ [LTMCrc] A double \.@ denotes the single character `\.@'. This is
+the only control code that is legal everywhere.
+Note that you must use this convention if you are giving an internet
+email address in a \.{CWEB} file (e.g., \.{levy@@math.berkeley.edu}).
+
+\subsec
+Here are the codes that introduce the \TEX/ part of a section.
+
+\@\ [LTMC\to T] This denotes the beginning of a new (unstarred)
+section. A tab mark or form feed or
+end-of-line character is equivalent to a space when it follows an \.@
+sign (and in most other cases).
+
+\@* [LTMC\to T] This denotes the beginning of a new starred
+section, i.e., a section that begins a new major group. The title of the new
+group should appear after the \.{@*}, followed by a period. As explained
+above, \TEX/ control sequences should be avoided in such titles unless
+they are quite simple. When \.{CWEAVE} and \.{CTANGLE} read a \.{@*}, they
+print an asterisk on the terminal
+followed by the current section number, so that the user
+can see some indication of progress. The very first section should be starred.
+
+\more You can specify the ``depth'' of a starred section by typing \.* or a
+decimal number after the \.{@*}; this indicates the relative ranking
+of the current group of sections in the program hierarchy. Top-level
+portions of the program, introduced by \.{@**}, get their names typeset
+in boldface type in the table of contents; they are said to have
+depth~$-1$. Otherwise the depth is a nonnegative number, which governs
+the amount of indentation on the contents page. Such indentation helps
+clarify the structure of a long program. The depth is assumed to be 0
+if it is not specified explicitly; when your program is short, you
+might as well leave all depths zero. A starred section always begins
+a new page in the output, unless the depth is greater than~1.
+
+\subsec
+The middle part of each section consists of any number of
+macro definitions (beginning with \.{@d}) and format definitions (beginning
+with \.{@f} or \.{@s}), intermixed in any order.
+
+\@d [TM\to M] Macro definitions begin with \.{@d}, followed by
+an identifier and optional parameters and \CEE/ text as explained earlier.
+
+\@f [TM\to M] Format definitions begin with \.{@f}; they cause
+\.{CWEAVE} to treat identifiers in a special way when they appear in
+\CEE/ text. The general form of a format definition is `\.{@f} \|l
+\|r', followed by an optional comment enclosed between
+\.{/*} and \.{*/}, where \|l and \|r
+are identifiers; \.{CWEAVE} will subsequently treat identifier \|l as it
+currently treats \|r. This feature allows a \.{CWEB} programmer to invent
+new reserved words and/or to unreserve some of \CEE/'s reserved
+identifiers. For example, the common words `error' and `line'
+have been given a special meaning in the \CEE/ preprocessor,
+so \.{CWEAVE} is set up to format them specially; if you want a variable
+named \\{error} or \\{line}, you should say
+$$\.{@f error normal}\qquad\qquad\.{@f line normal}$$
+somewhere in your program.
+
+\more If \|r is the special identifier `\\{TeX}', identifier \|l
+will be formatted as a \TEX/ control sequence; for example,
+`\.{@f foo TeX}' in the \.{CWEB} file will cause identifier \\{foo} to
+be output as \.{\\foo} by \.{CWEAVE}. The programmer should define
+\.{\\foo} to have whatever custom format is desired, assuming \TEX/
+math mode. (Each underline
+character is converted to \.{x} when making the \TEX/ control sequence,
+and each dollar sign is converted to~\.X;
+thus \\{foo\_bar} becomes \.{\\fooxbar}. Other characters, including digits,
+are left untranslated, so \TEX/ will consider them as macro parameters,
+not as part of the control sequence itself. For example,
+$$\.{\\def\\x\#1\{x\_\{\#1\}\} @f x1 TeX @f x2 TeX}$$
+will format \.{x1} and \.{x2} not as \\{x1} and \\{x2} but as $x_1$ and $x_2$.)
+
+\more If \|r is the special identifier `\\{make\_pair}', identifier \|l will
+be treated as a \CPLUSPLUS/ function template. For example, after
+\.{@f}~\.{convert}~\.{make\_pair} one can say `\.{convert<int>(2.5)}' without
+having \.< and \.> misunderstood as less-than and greater-than signs.
+
+\more \.{CWEAVE} knows that identifiers being
+defined with a \&{typedef} should become reserved words; thus you
+don't need format definitions very often.
+
+\@s [TM\to M;\;L] Same as \.{@f}, but \.{CWEAVE} does not show the format
+definition in the output, and the optional \CEE/ comment is not
+allowed. This is used mostly in \.{@i} files.
+
+\subsec
+Next come the codes that govern the \CEE/ part of a section.
+
+\@{c @p} [TM\to C] The \CEE/ part of an unnamed section begins with \.{@c}
+(or with \.{@p} for ``program''; both control codes do the same thing).
+This causes \.{CTANGLE} to append the following \CEE/ code
+to the first-order program text, as explained on page~\tangref.
+Note that \.{CWEAVE} does not print a `\.{@c}' in the \TEX/
+output, so if you are creating a \.{CWEB} file based on a \TEX/-printed
+\.{CWEB} documentation you have to remember to insert \.{@c} in the
+appropriate places of the unnamed sections.
+
+\@< [TM\to C;\; C;\; c] $*$ This control code introduces a
+section name (or unambiguous prefix, as discussed above), which
+consists of \TEX/ text and extends to the matching \.{@>}.
+The whole construct \.{@<...@>} is conceptually a \CEE/ element.
+The behavior is different depending on the context:
+
+\more A \.{@<} appearing in contexts $T$ and $M$ attaches the
+following section name to the current section, and inaugurates the
+\CEE/ part of the section. The closing \.{@>} should be followed by
+\.{=} or \.{+=}.
+
+\more
+In context $C$, \.{@<} indicates that the named
+section is being used---its \CEE/ definition is spliced in by
+\.{CTANGLE}, as explained on page~\tangref.
+As an error-detection measure,
+\.{CTANGLE} and \.{CWEAVE} complain if such a section name is followed
+by \.=, because most likely this is meant as the definition of a new
+section, and so should be preceded by \.{@\ }. If you really want to
+say $\langle\,$foo$\,\rangle=\\{bar}$, where $\langle\,$foo$\,\rangle$
+is being used and not defined, put a newline before the \.=.
+
+\more
+Finally, in inner \CEE/ context (that is, within `\pb' in the \TEX/ part
+of a section or in a comment), \.{@<...@>}
+means that the named section is being
+cited. Such an occurrence is ignored by \.{CTANGLE}. Note that
+even here we think of the section name as being a \CEE/ element, hence the \pb.
+
+\@( [TM\to C;\;C;\;c] $*$ A section name can begin with \.{@(}.
+Everything works just as for \.{@<}, except that the \CEE/ code
+of the section named \.{@(foo@>} is written by \.{CTANGLE}
+to file \.{foo}. In this way you can get multiple-file output from
+a single \.{CWEB} file. (The \.{@d} definitions are not output
+to such files, only to the master \.{.c} file.) One use of this feature
+is to produce header files for other program modules that will be loaded
+with the present one. Another use is to produce a test routine that
+goes with your program. By keeping the sources for a program and its
+header and test routine together, you are more likely to keep
+all three consistent with each other. Notice that the output of a named
+section can be incorporated in several different output files, because
+you can mention \.{@<foo@>} in both \.{@(bar1@>} and \.{@(bar2@>}.
+
+\@h [Cc] Causes \.{CTANGLE}
+to insert at the current spot the \.{\#define} statements
+from the middle parts of all sections,
+and {\it not\/} to write them at the beginning of the \CEE/ file.
+Useful when you want the macro definitions to come after the include files,
+say. (Ignored by \.{CTANGLE} inside `\pb'.)
+
+\subsec
+The next several control codes introduce ``control
+texts,'' which end with the next `\.{@>}'. The closing `\.{@>}' must be on
+the same line of the \.{CWEB} file as the line where the control text began.
+The context from each of these control codes to the matching \.{@>} is
+restricted.
+
+\@\^ [TMCc] $*$ The control text that follows, up to the next
+`\.{@>}', will be entered into the index together with the identifiers of
+the \CEE/ program; this text will appear in roman type. For example, to
+put the phrase ``system dependencies'' into the index that is output by
+\.{CWEAVE}, type
+`\.{@\^system dependencies@>}' in each section
+that you want to index as system dependent.
+
+\@. [TMCc] $*$ The control text that follows will be entered into the index
+in \.{typewriter} \.{type}.
+
+\@: [TMCc] $*$ The control text that follows will be entered into the index
+in a format controlled by the \TEX/ macro `\.{\\9}', which you
+should define as desired.
+
+\@t [MCc] $*$ The control text that follows will
+be put into a \TEX/ \.{\\hbox} and formatted along with the neighboring
+\CEE/ program. This text is ignored by \.{CTANGLE}, but it can be used
+for various purposes within \.{CWEAVE}. For example, you can make comments
+that mix \CEE/ and classical mathematics, as in `$\\{size}<2^{15}$', by
+typing `\.{|size < 2@t\$\^\{15\}\$@>|}'.
+
+\@= [MCc] $*$ The control text that follows will
+be passed verbatim to the \CEE/ program.
+
+\@q [LTMCc] $*$ The control text that follows will
+be totally ignored---it's a comment for readers of the \.{CWEB} file only.
+A file intended to be included in
+limbo, with \.{@i}, can identify itself with \.{@q} comments.
+Another use is to balance unbalanced parentheses in C strings,
+so that your text editor's parenthesis matcher doesn't go into a tailspin.
+
+\@! [TMCc] $*$
+The section number in an index entry will be underlined if `\.{@!}'
+immediately precedes the identifier or control text being indexed. This
+convention is used to distinguish the sections where an identifier is
+defined, or where it is explained in some special way, from the sections
+where it is used. A~reserved word or an identifier of length one will not
+be indexed except for underlined entries. An `\.{@!}' is implicitly inserted
+by \.{CWEAVE} when an identifier is being defined or declared in \CEE/
+code; for example, the definition
+$$\hbox{\&{int} \\{array}[\\{max\_dim}], \\{count}${}=\\{old\_count};$}$$
+makes the names \\{array} and \\{count} get an underlined entry in the
+index. Statement labels, function definitions like
+\\{main}(\&{int}~\\{argc},\,\&{char}~$*$\\{argv}[\,]),
+and \&{typedef} definitions also
+imply underlining. An old-style
+function definition (without prototyping) doesn't define its arguments;
+the arguments will, however, be considered to be defined
+(i.e., their index entries will be underlined) if their types are
+declared before the body of the function in the usual way
+(e.g., `\&{int}~\\{argc}; \&{char}~${*}\\{argv}[\,]$; $\{\,\ldots\,\}$').
+Thus \.{@!} is not needed very often, except in unusual constructions
+or in cases like
+$$\.{enum boolean \{@!false, @!true\};}$$
+here \.{@!} gives the best results because individual constants enumerated
+by \.{enum} are not automatically underlined in the index at their
+point of definition.
+
+\subsec
+We now turn to control codes that affect only the operation of
+\.{CTANGLE}.
+
+\@' [MCc] This control code is dangerous because it has quite different
+meanings in \.{CWEB} and the original \.{WEB}. In \.{CWEB} it produces the
+decimal constant corresponding to the ASCII code for a string of length~1
+(e.g., \.{@'a'} is \.{CTANGLE}d into \.{97} and \.{@'\\t'} into
+\.9). You might want to use this if you need to work in ASCII on a
+non-ASCII machine; but in most cases the \CEE/ conventions of
+\.{<ctype.h>} are adequate for character-set-independent programming.
+
+\@\& [MCc] The \.{@\&} operation causes whatever is on its left to be
+adjacent to whatever is on its right, in the \CEE/ output. No spaces or
+line breaks will separate these two items.
+
+\@l [L] \.{CWEB} programmers have the option of using any 8-bit character
+code from the often-forbidden range 128--255 within \TEX/ text; such
+characters are also permitted in strings and even in identifiers of the
+\CEE/ program.
+Under various extensions of the basic
+ASCII standard, the higher 8-bit codes correspond
+to accented letters, letters from non-Latin alphabets,
+and so on. When such characters occur in identifiers, \.{CTANGLE} must replace
+them by standard ASCII alphanumeric characters or
+\.{\_}, in order to generate legal \CEE/ code. It does this by means
+of a transliteration table, which by default associates the string
+\.{Xab} to the character with ASCII code \T{\^}$ab$ (where $a$ and $b$ are
+hexadecimal digits, and $a\ge8$). By placing the
+construction \.{@l\ ab\ newstring} in limbo, you are telling
+\.{CTANGLE} to replace this character by \.{newstring} instead.
+For example, the ISO Latin-1 code for the letter `\"u' is \T{\^FC}
+(or \.{'\char`\\374'}),
+and \.{CTANGLE} will normally change this code to the
+three-character sequence \.{XFC} if it
+appears in an identifier. If you say \.{@l} \.{fc} \.{ue}, the code will
+be transliterated into \.{ue} instead.
+
+\more
+\.{CWEAVE} passes 8-bit characters straight through to \TEX/ without
+transliteration; therefore \TEX/ must be prepared to receive them.
+If you are formatting all your nonstandard identifiers as ``custom''
+control sequences, you should
+make \TEX/ treat all their characters as letters. Otherwise you should either
+make your 8-bit codes ``active'' in \TEX/, or load fonts that
+contain the special characters you need in the correct positions.
+(The font selected by \TEX/ control sequence \.{\\it} is used for
+identifiers.)
+Look for special macro packages designed for \.{CWEB} users in your language;
+or, if you are brave, write one yourself.
+
+\subsec
+The next eight control codes (namely `\.{@,}', `\.{@/}', `\.{@|}', `\.{@\#}',
+`\.{@+}', `\.{@;}', `\.{@[}', and `\.{@]}') have no effect on the \CEE/
+program output by \.{CTANGLE}; they merely help to improve the readability
+of the \TEX/-formatted \CEE/ that is output by \.{CWEAVE}, in unusual
+circumstances. \.{CWEAVE}'s built-in formatting method is fairly good
+when dealing with syntactically correct \CEE/ text, but
+it is incapable of handling all possible cases, because it must deal with
+fragments of text involving macros and section names; these fragments do
+not necessarily obey \CEE/'s syntax. Although \.{CWEB} allows you to
+override the automatic formatting, your best strategy is not to worry
+about such things until you have seen what \.{CWEAVE} produces automatically,
+since you will probably need to make only a few corrections when you are
+touching up your documentation.
+
+\@, [MCc] This control code inserts a thin space in \.{CWEAVE}'s output.
+Sometimes you need this extra space if you are using
+macros in an unusual way, e.g., if two identifiers are adjacent.
+
+\@/ [MC] This control code causes a line break to occur within a \CEE/
+program formatted by \.{CWEAVE}. Line breaks
+are chosen automatically by \TEX/ according to a scheme that works 99\%\
+of the time, but sometimes you will prefer to force a line break so that
+the program is segmented according to logical rather than visual
+criteria. If a comment follows, say `\.{@/@,}' to break the line
+before the comment.
+
+\@| [MC] This control code specifies an optional line break in the midst of
+an expression. For example, if you have
+a long expression on the right-hand side of an assignment
+statement, you can use `\.{@|}' to specify breakpoints more logical than
+the ones that \TEX/ might choose on visual grounds.
+
+\@\# [MC] This control code forces a line break, like \.{@/} does,
+and it also causes a little extra white space to appear between the lines at
+this break. You might use it, for example,
+between groups of macro definitions that are logically separate but within
+the same section. \.{CWEB} automatically inserts this extra space
+between functions, between external declarations and functions, and
+between declarations and statements within a function.
+
+\@+ [MC] This control code cancels a line break that might otherwise be
+inserted by \.{CWEAVE}, e.g., before the word `\&{else}', if you want to
+put a short if--else construction on a single line.
+If you say `\.{\{@+}' at the beginning of a compound statement
+that is the body of a function, the first declaration or
+statement of the function will appear on the same line as the
+left brace, and it will be indented by the same amount as the
+second declaration or statement on the next line.
+
+\@; [MC] This control code is treated like a semicolon, for formatting
+purposes, except that it is invisible. You can use it, for example, after
+a section name or macro when the \CEE/ text represented by that section or macro
+is a compound statement or ends
+with a semicolon. Consider constructions like
+$$\lpile{\.{if (condition) macro @;}\cr
+\.{else break;}\cr}$$
+where \\{macro} is defined to be a compound statement (enclosed in braces).
+This is a well-known infelicity of \CEE/ syntax.
+
+\@{[} [MC] See \.{@]}.
+
+\@] [MC] Place \.{@[...@]} brackets around program text that \.{CWEAVE} is
+supposed to format as an expression, if it doesn't already do so. (This
+occasionally applies to unusual macro arguments.) Also
+insert `\.{@[@]}' between a simple type name and a left parenthesis
+when declaring a pointer to a function, as in
+$$\.{int @[@] (*f)();}$$
+otherwise \.{CWEAVE} will confuse the first part of that declaration with
+the \CPLUSPLUS/ expression `\&{int}($*f$)'. Another example, for people
+who want to use low-level \.{\#define} commands in the midst of \CEE/ code
+and the definition begins with a cast:
+$$\.{\#define foo @[(int)(bar)@]}$$
+
+\subsec
+The remaining control codes govern the input that \.{CWEB} sees.
+
+\@{x @y @z}[\\{change\_file}]
+\.{CWEAVE} and \.{CTANGLE} are designed to work with two input files,
+called \\{web\_file} and \\{change\_file}, where \\{change\_file} contains
+data that overrides selected portions of \\{web\_file}. The resulting merged
+text is actually what has been called the \.{CWEB} file elsewhere in this
+report.
+
+\more Here's how it works: The change file consists of zero or more ``changes,''
+where a change has the form `\.{@x}$\langle$old lines$\rangle$\.{@y}$\langle$%
+new lines$\rangle$\.{@z}'. The special control codes \.{@x}, \.{@y}, \.{@z},
+which are allowed only in change files, must appear at the beginning of a line;
+the remainder of such a line is ignored.
+The $\langle$old lines$\rangle$ represent material that exactly matches
+consecutive lines of the \\{web\_file}; the $\langle$new lines$\rangle$
+represent zero or more lines that are supposed to replace the old. Whenever
+the first ``old line'' of a change is found to match a line in the
+\\{web\_file}, all the other lines in that change must match too.
+
+\more Between changes, before the first change, and after the last change,
+the change file can have any number of lines that do not begin with
+`\.{@x}', `\.{@y}', or~`\.{@z}'. Such lines are bypassed and not used for
+matching purposes.
+
+\more This dual-input feature is useful when working with a master \.{CWEB}
+file that has been received from elsewhere (e.g., \.{tangle.w} or
+\.{weave.w} or \.{tex.web}), when changes are desirable to customize the
+program for your local computer system. You will be able to debug your
+system-dependent changes without clobbering the master web file; and once
+your changes are working, you will be able to incorporate them readily
+into new releases of the master web file that you might receive from time
+to time.
+
+\@i [\\{web\_file}]
+Furthermore the \\{web\_file} itself can be a combination of
+several files. When either \.{CWEAVE} or \.{CTANGLE} is reading a file and
+encounters the control code \.{@i} at the beginning of a line, it
+interrupts normal reading and starts looking at the file named after the
+\.{@i}, much as the \CEE/ preprocessor does when it encounters an \.{\#include}
+line. After the included file has been entirely read, the program
+goes back to the next line
+of the original file. The file name following \.{@i} can be
+surrounded by \." characters, but such delimiters are
+optional. Include files can nest.
+
+\more
+Change files can have lines starting with \.{@i}. In this way
+you can replace one included file with another. Conceptually, the
+replacement mechanism described above does its work first, and
+its output is then checked for \.{@i} lines. If \.{@i} \.{foo}
+occurs between \.{@y} and \.{@z} in a change file, individual lines
+of file \.{foo} and files it includes are not changeable; but changes
+can be made to lines from files that were included by unchanged input.
+
+\more On UNIX systems (and others that support environment variables),
+if the environment variable \.{CWEBINPUTS} is set, or if the compiler flag
+of the same name was defined at compile time,
+\.{CWEB} will look for include files in the directory thus named, if
+it cannot find them in the current directory.
+
+\section Additional features and caveats.
+
+1. In certain installations of \.{CWEB} that
+{\def\\#1#2{`{\tentex\char'#1#2}'}%
+have an extended character set, the characters
+\\13, \\01, \\31, \\32, \\34, \\35,
+\\36, \\37, \\04, \\20, and \\21}
+can be typed as abbreviations for `\.{++}', `\.{--}', `\.{->}',
+`\.{!=}', `\.{<=}', `\.{>=}', `\.{==}', `\.{\v\v}', `\.{\&\&}',
+`\.{<<}', and `\.{>>}',
+respectively.
+
+2. If you have an extended character set, you can use it with only minimal
+restrictions, as discussed under the rules for \.{@l} above. But you should
+stick to standard ASCII characters if you want to write programs that will
+be useful to all the poor souls out there who don't have extended
+character sets.
+
+3. The \TEX/ file output by \.{CWEAVE} is broken into lines having at most
+80 characters each. When
+\TEX/ text is being copied, the existing line breaks are copied as well.
+If you aren't doing anything too tricky, \.{CWEAVE} will recognize when
+a \TEX/ comment is being split across two or more lines, and it will
+append `\.\%' to the beginning of such continued comments.
+
+4. \CEE/ text is translated by a ``bottom up'' procedure that
+identifies each token as a ``part of speech'' and combines parts of speech
+into larger and larger phrases as much as possible according to a special
+grammar that is explained in the documentation of \.{CWEAVE}. It is easy to
+learn the translation scheme for simple constructions like single
+identifiers and short expressions, just by looking at a few examples of
+what \.{CWEAVE} does, but the general mechanism is somewhat complex because
+it must handle much more than \CEE/ itself. Furthermore the output
+contains embedded codes that cause \TEX/ to indent and break lines as
+necessary, depending on the fonts used and the desired page width. For
+best results it is wise to avoid enclosing long \CEE/ texts in \pb, since the
+indentation and line breaking codes are omitted when the \pb\ text is
+translated from \CEE/ to \TEX/. Stick to simple expressions or
+statements. If a \CEE/ preprocessor command is enclosed in \pb,
+the \.\# that introduces it must be at the beginning of a line,
+or \.{CWEAVE} won't print it correctly.
+
+5. Comments are not permitted in \pb\ text. After a `\.|'
+signals the change from \TEX/ text to \CEE/ text, the next `\.|' that is
+not part of a string or control text or section name ends the \CEE/ text.
+
+6. A comment must have properly nested occurrences of left and right
+braces, otherwise \.{CWEAVE} will complain. But it
+does try to balance the braces, so that \TEX/ won't foul up too much.
+
+7. When you're debugging a program and decide to omit some of your
+\CEE/ code, do NOT simply ``comment it out.'' Such comments are not
+in the spirit of \.{CWEB} documentation; they will appear to readers
+as if they were explanations of the uncommented-out instructions.
+Furthermore, comments of a program must be valid \TEX/ text; hence
+\.{CWEAVE} will get confused if you enclose \CEE/ statements in
+\.{/*...*/} instead of in \.{/*|...|*/}. If you must comment out
+\CEE/ code, you can surround it with preprocessor commands
+like \.{\#if 0==1} and \.{\#endif}.
+
+8. The \.{@f} feature allows you to define one identifier to act like
+another, and these format definitions are carried out sequentially.
+In general, a given identifier has only one printed format
+throughout the entire document, and this format is used even before
+the \.{@f} that defines it. The reason is that \.{CWEAVE} operates in two
+passes; it processes \.{@f}'s and cross-references on the first pass and
+it does the output on the second. (However, identifiers that
+implicitly get a boldface format, thanks to a \.{typedef} declaration,
+don't obey this rule; they are printed differently before and after
+the relevant \.{typedef}. This is unfortunate, but hard to fix. You can
+get around the restriction by saying, say, `\.{@s} \.{foo} \.{int}',
+before or after the \.{typedef}.)
+
+9. Sometimes it is desirable to insert spacing into formatted \CEE/ code that
+is more general than the thin space provided by `\.{@,}'. The \.{@t} feature
+can be used for this purpose; e.g., `\.{@t\\hskip 1in@>}' will
+leave one inch of blank space. Furthermore, `\.{@t\\4@>}' can be
+used to backspace by one unit of indentation, since the control sequence
+\.{\\4} is defined in \.{cwebmac} to be such a backspace. (This
+control sequence is used, for example, at the beginning of lines that
+contain labeled statements, so that the label will stick out a little at
+the left.) You can also use `\.{@t\}\\3\{-5@>}' to force a break
+in the middle of an expression.
+
+10. Each identifier in \.{CWEB} has a single formatting convention. Therefore
+you shouldn't use the same identifier to denote, say, both a type name and
+part of a \.{struct}, even though \CEE/ does allow this.
+
+\section Running the programs.
+The \UNIX/ command line for \.{CTANGLE} is
+$$\.{ctangle [options] web\_file[.w] [\{change\_file[.ch]|-\} [out\_file]]}$$
+and the same conventions apply to \.{CWEAVE}. If `\.-' or no change file is
+specified, the change file is null. The extensions \.{.w} and \.{.ch}
+are appended only if the given file names contain no dot. If the
+web file defined in this way cannot be found, the extension \.{.web}
+will be tried. For example, `\.{cweave} \.{cob}' will try to read
+\.{cob.w}; failing that, it will try \.{cob.web} before giving up.
+If no output file name is specified, the name of the \CEE/ file output by
+\.{CTANGLE} is obtained by appending the extension \.{.c};
+the name of the \TEX/ file output by \.{CWEAVE} gets the extension \.{.tex}.
+Index files output by \.{CWEAVE} replace \.{.tex} by \.{.idx} and \.{.scn}.
+
+Programmers who like terseness might choose to set up their
+ operating shell so that `\.{wv}' expands to
+`\.{cweave -bhp}'; this will suppress most terminal output from \.{CWEAVE}
+except for error messages.
+
+Options are introduced either by a \.- sign, to turn an option off,
+or by a \.+ sign to turn one on. For example, `\.{-fb}' turns off
+options \.f and \.b; `\.{+s}' turns on option \.s. Options can be
+specified before the file names, after the file names, or both. The following
+options are currently implemented:
+
+\yskip
+\def\option#1 {\textindent{\.#1}\hangindent2\parindent}
+
+\option b Print a banner line at the beginning of execution. (On
+by default.)
+
+\option e Enclose \CEE/ material formatted by \.{CWEAVE} in
+brackets \.{\\PB\{...\}}, so that special hooks can be used.
+(Off by default; has no effect on \.{CTANGLE}.)
+
+\option f Force line breaks after each \CEE/ statement formatted
+by \.{CWEAVE}. (On by default; \.{-f} saves paper but looks less \CEE/-like
+to some people.) (Has no effect on \.{CTANGLE}.)
+
+\option h Print a happy message at the conclusion of a successful
+run. (On by default.)
+
+\option p Give progress reports as the program runs. (On by default.)
+
+\option s Show statistics about memory usage after the program
+runs to completion. (Off by default.)
+If you
+have large \.{CWEB} files or sections, you may need to see
+how close you come to exceeding the capacity of \.{CTANGLE} and/or \.{CWEAVE}.
+
+\option x Include indexes and a table of contents in the \TEX/ file
+output by \.{CWEAVE}. (On by default.) (Has no effect on \.{CTANGLE}.)
+
+\section Further details about formatting.
+You may not like the way \.{CWEAVE} handles certain
+situations. If you're desperate, you can customize \.{CWEAVE}
+by changing its grammar. This means changing the source code,
+a task that you might find amusing. A table of grammar rules
+appears in the \.{CWEAVE} source listing, and you can make a separate
+copy of that table by copying the file \.{prod.w} found in the \.{CWEB}
+sources and saying `\.{cweave}~\.{-x}~\.{prod}', followed by
+`\.{tex}~\.{prod}'.
+
+You can see exactly
+how \.{CWEAVE} is parsing your \CEE/ code by preceding
+it with the line `\.{@ @c @2}'. (The control code `\.{@2}'
+turns on a ``peeping'' mode, and `\.{@0}' turns it off.)
+For example, if you run \.{CWEAVE} on the file
+\medskip
+\begingroup
+\verbatim
+@ @c @2
+main (argc,argv)
+char **argv;
+{ for (;argc>0;argc--) printf("%s\n",argv[argc-1]); }
+!endgroup
+\endgroup
+\medskip\noindent
+you get the following gibberish on your screen:
+\medskip
+\begingroup
+\verbatim
+[...]
+4:*exp ( +exp+ )...
+11:*exp +exp+ int...
+5:*+exp+ int +unorbinop+...
+[...]
+60: +fn_decl+*+{+ -stmt- +}-
+55:*+fn_decl+ -stmt-
+52:*+function-
+[...]
+!endgroup
+\endgroup
+\medskip
+The first line says that grammar rule 4 has just been applied, and \.{CWEAVE}
+currently has in its memory a sequence of chunks of \TEX/ code (called
+``scraps'') that are respectively
+of type \\{exp} (for expression), open-parenthesis,
+\\{exp} again, close-parenthesis, and further scraps that haven't yet
+been considered by the parser. (The \.+ and \.- signs stipulate that
+\TEX/ should be in or out of math mode at the scrap boundaries. The \.* shows
+the parser's current position.)
+Then rule 11 is applied, and
+the sequence $(\,exp\,)$ becomes an \\{exp} and so on. In the
+end the whole \CEE/ text has become one big scrap of type \\{function}.
+
+Sometimes things don't work as smoothly, and you get a bunch of
+lines lumped together. This means that \.{CWEAVE} could not
+digest something in your \CEE/ code. For instance, suppose
+`\.{@<Argument definitions@>}' had appeared instead of
+`\.{char **argv;}' in the program above. Then \.{CWEAVE} would have
+been somewhat mystified, since it thinks that section names
+are just \\{exp}s. Thus it would tell \TEX/ to format
+`\X2:Argument declarations\X' on the same line as
+`$\\{main}(\\{argc},\39\\{argv}{}$)'.
+In this case you should help \.{CWEAVE} by putting `\.{@/}' after
+`\.{main(argc,argv)}'.
+
+\.{CWEAVE} automatically inserts a bit of extra space between declarations
+and the first apparent statement of a block. One way to defeat this
+spacing locally is
+$$\vbox{\halign{#\hfil\cr
+\.{int x;@+@t\}\\6\{@>}\cr
+\.{@<Other locals@>@;@\#}\cr}}$$
+the `\.{@\#}' will put extra space after `$\langle\,$Other locals$\,\rangle$'.
+
+\section Hypertext and hyperdocumentation.
+
+Many people have of course noticed analogies between \.{CWEB} and the
+World Wide Web. The \.{CWEB} macros are in fact set up so that the output of
+\.{CWEAVE} can be converted easily into Portable Document Format,
+with clickable hyperlinks that can be read with Adobe's Acrobat Reader,
+using a widely available open-source program called \.{dvipdfm} developed
+by Mark~A. Wicks. After using \.{CWEAVE} to convert \.{cob.w} into
+\.{cob.tex}, you can prepare and view a hypertext version of the program
+by giving the commands
+$$\vbox{\halign{\.{#}\hfil\cr
+tex "\\let\\pdf+ \\input cob"\cr
+dvipdfm cob\cr
+acroread cob.pdf\cr}}$$
+instead of invoking \TeX\ in the normal way. (Thanks to Hans Hagen,
+C\'esar Augusto Rorato Crusius, and Julian Gilbey
+for the macros that make this work.)
+Alternatively, thanks to H\`an Th\^e\kern-.3em\raise.3ex\hbox{\'{}} Th\`anh
+and Andreas Scherer, you can generate \.{cob.pdf} in one step by simply
+saying `\.{pdftex}~\.{cob}'.
+
+A more elaborate system called \.{CTWILL}, which extends the usual cross
+references of \.{CWEAVE} by preparing links from the uses of identifiers
+to their definitions, is also available---provided that you are willing
+to work a bit harder in cases where an identifier is multiply defined.
+\.{CTWILL} is intended primarily for hardcopy output, but its principles
+could be used for hypertext as well.
+See Chapter 11 of {\sl Digital Typography\/} by D.~E. Knuth (1999), and
+the program sources at \.{ftp://labrea.stanford.edu/pub/ctwill}.
+
+\section Appendices.
+
+As an example of a real program written in \.{CWEB}, Appendix~A
+contains an excerpt from the \.{CWEB} program itself. The reader who
+examines the listings in this appendix carefully will get a good
+feeling for the basic ideas of \.{CWEB}.
+
+Appendix B is the file that sets \TEX/ up to accept
+the output of \.{CWEAVE}, and Appendix~C discusses how to use some of those
+macros to vary the output formats.
+
+A ``long'' version of this manual, which can be produced from the \.{CWEB}
+sources via the \UNIX/ command \.{make} \.{fullmanual}, also contains
+appendices D, E, and~F, which exhibit the complete source code for
+\.{CTANGLE} and \.{CWEAVE}.
+
+\vfil\eject\titletrue
+
+\def\runninghead{APPENDIX A --- {\tentt CWEB} FILE FORMAT}
+\section Appendix A: Excerpts from a \.{CWEB} Program.
+
+This appendix consists
+of four listings. The first shows the \.{CWEB} input that
+generated sections 12--15 of the file \.{common.w}, which contains
+routines common to \.{CWEAVE} and \.{CTANGLE}.
+Note that some of the lines are indented to show the program structure;
+the indentation is ignored by \.{CWEAVE} and \.{CTANGLE}, but users find
+that \.{CWEB} files are quite readable if they have some such indentation.
+
+The second and third listings
+show corresponding parts
+of the \CEE/ code output by \.{CTANGLE} and of
+the corresponding \TEX/ code output by \.{CWEAVE}, when run on \.{common.w}.
+The fourth listing shows how that output looks when printed out.
+
+\vskip 6pt
+\begingroup \def\tt{\eighttt} \baselineskip9pt
+\verbatim
+@ Procedure |prime_the_change_buffer|
+sets |change_buffer| in preparation for the next matching operation.
+Since blank lines in the change file are not used for matching, we have
+|(change_limit==change_buffer && !!changing)| if and only if
+the change file is exhausted. This procedure is called only when
+|changing| is 1; hence error messages will be reported correctly.
+
+@c
+void
+prime_the_change_buffer()
+{
+ change_limit=change_buffer; /* this value is used if the change file ends */
+ @<Skip over comment lines in the change file; |return| if end of file@>;
+ @<Skip to the next nonblank line; |return| if end of file@>;
+ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+}
+
+@ While looking for a line that begins with \.{@@x} in the change file, we
+allow lines that begin with \.{@@}, as long as they don't begin with \.{@@y},
+\.{@@z}, or \.{@@i} (which would probably mean that the change file is fouled up).
+
+@<Skip over comment lines in the change file...@>=
+while(1) {
+ change_line++;
+ if (!!input_ln(change_file)) return;
+ if (limit<buffer+2) continue;
+ if (buffer[0]!!='@@') continue;
+ if (xisupper(buffer[1])) buffer[1]=tolower(buffer[1]);
+ if (buffer[1]=='x') break;
+ if (buffer[1]=='y' || buffer[1]=='z' || buffer[1]=='i') {
+ loc=buffer+2;
+ err_print("!! Missing @@x in change file");
+@.Missing @@x...@>
+ }
+}
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do {
+ change_line++;
+ if (!!input_ln(change_file)) {
+ err_print("!! Change file ended after @@x");
+@.Change file ended...@>
+ return;
+ }
+} while (limit==buffer);
+
+@ @<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+{
+ change_limit=change_buffer-buffer+limit;
+ strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+!endgroup
+\endgroup
+\vfill\eject
+
+\def\runninghead{APPENDIX A --- TRANSLATION BY {\tentt CTANGLE}}
+
+Here's the portion of the \CEE/ code generated by \.{CTANGLE} that corresponds
+to the source on the preceding page. Notice that sections~13, 14 and~15
+have been tangled into section~12.
+
+\vskip6pt
+\begingroup \def\tt{\eighttt} \baselineskip9pt
+\verbatim
+/*:9*//*12:*/
+#line 247 "common.w"
+
+void
+prime_the_change_buffer()
+{
+change_limit= change_buffer;
+/*13:*/
+#line 261 "common.w"
+
+while(1){
+change_line++;
+if(!!input_ln(change_file))return;
+if(limit<buffer+2)continue;
+if(buffer[0]!!='@')continue;
+if(xisupper(buffer[1]))buffer[1]= tolower(buffer[1]);
+if(buffer[1]=='x')break;
+if(buffer[1]=='y'||buffer[1]=='z'||buffer[1]=='i'){
+loc= buffer+2;
+err_print("!! Missing @x in change file");
+
+}
+}
+
+/*:13*/
+#line 252 "common.w"
+;
+/*14:*/
+#line 278 "common.w"
+
+do{
+change_line++;
+if(!!input_ln(change_file)){
+err_print("!! Change file ended after @x");
+
+return;
+}
+}while(limit==buffer);
+
+/*:14*/
+#line 253 "common.w"
+;
+/*15:*/
+#line 288 "common.w"
+
+{
+change_limit= change_buffer-buffer+limit;
+strncpy(change_buffer,buffer,limit-buffer+1);
+}
+
+/*:15*/
+#line 254 "common.w"
+;
+}
+
+/*:12*//*16:*/
+!endgroup
+\endgroup
+\vfill\eject
+
+\def\runninghead{APPENDIX A --- TRANSLATION BY {\tentt CWEAVE}}
+
+Here is the corresponding excerpt from \.{common.tex}.
+
+\vskip6pt
+\begingroup \def\tt{\eighttt} \baselineskip9pt
+\verbatim
+\M{12}Procedure \PB{\\{prime\_the\_change\_buffer}}
+sets \PB{\\{change\_buffer}} in preparation for the next matching operation.
+Since blank lines in the change file are not used for matching, we have
+\PB{$(\\{change\_limit}\E\\{change\_buffer}\W\R\\{changing})$} if and only if
+the change file is exhausted. This procedure is called only when
+\PB{\\{changing}} is 1; hence error messages will be reported correctly.
+!vskip-.5!baselineskip
+\Y\B\&{void} \\{prime\_the\_change\_buffer}(\,)\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{change\_limit}\K\\{change\_buffer}{}$;\C{ this value is used if the
+change file ends }\6
+\X13:Skip over comment lines in the change file; \PB{\&{return}} if end of file%
+\X;\6
+\X14:Skip to the next nonblank line; \PB{\&{return}} if end of file\X;\6
+\X15:Move \PB{\\{buffer}} and \PB{\\{limit}} to \PB{\\{change\_buffer}} and %
+\PB{\\{change\_limit}}\X;\6
+\4${}\}{}$\2\par
+\fi
+!vskip-.5!baselineskip
+\M{13}While looking for a line that begins with \.{@x} in the change file, we
+allow lines that begin with \.{@}, as long as they don't begin with \.{@y},
+\.{@z}, or \.{@i} (which would probably mean that the change file is fouled
+up).
+!vskip-.5!baselineskip
+\Y\B\4\X13:Skip over comment lines in the change file; \PB{\&{return}} if end
+of file\X${}\E{}$\6
+\&{while} (\T{1})\5
+${}\{{}$\1\6
+${}\\{change\_line}\PP;{}$\6
+\&{if} ${}(\R\\{input\_ln}(\\{change\_file})){}$\1\5
+\&{return};\2\6
+\&{if} ${}(\\{limit}<\\{buffer}+\T{2}){}$\1\5
+\&{continue};\2\6
+\&{if} ${}(\\{buffer}[\T{0}]\I\.{'@'}){}$\1\5
+\&{continue};\2\6
+\&{if} (\\{xisupper}(\\{buffer}[\T{1}]))\1\5
+${}\\{buffer}[\T{1}]\K\\{tolower}(\\{buffer}[\T{1}]);{}$\2\6
+\&{if} ${}(\\{buffer}[\T{1}]\E\.{'x'}){}$\1\5
+\&{break};\2\6
+\&{if} ${}(\\{buffer}[\T{1}]\E\.{'y'}\V\\{buffer}[\T{1}]\E\.{'z'}\V\\{buffer}[%
+\T{1}]\E\.{'i'}){}$\5
+${}\{{}$\1\6
+${}\\{loc}\K\\{buffer}+\T{2};{}$\6
+\\{err\_print}(\.{"!!\ Missing\ @x\ in\ cha}\)\.{nge\ file"});\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\U12.\fi
+!vskip-.5!baselineskip
+\M{14}Here we are looking at lines following the \.{@x}.
+!vskip-.5!baselineskip
+\Y\B\4\X14:Skip to the next nonblank line; \PB{\&{return}} if end of file\X${}%
+\E{}$\6
+\&{do}\5
+${}\{{}$\1\6
+${}\\{change\_line}\PP;{}$\6
+\&{if} ${}(\R\\{input\_ln}(\\{change\_file})){}$\5
+${}\{{}$\1\6
+\\{err\_print}(\.{"!!\ Change\ file\ ended}\)\.{\ after\ @x"});\6
+\&{return};\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\5
+\&{while} ${}(\\{limit}\E\\{buffer}){}$;\par
+\U12.\fi
+!vskip-.5!baselineskip
+\M{15}\B\X15:Move \PB{\\{buffer}} and \PB{\\{limit}} to \PB{\\{change\_buffer}}
+and \PB{\\{change\_limit}}\X${}\E{}$\6
+${}\{{}$\1\6
+${}\\{change\_limit}\K\\{change\_buffer}-\\{buffer}+\\{limit};{}$\6
+${}\\{strncpy}(\\{change\_buffer},\39\\{buffer},\39\\{limit}-\\{buffer}+%
+\T{1});{}$\6
+\4${}\}{}$\2\par
+\Us12\ET16.\fi
+!endgroup
+\endgroup
+\vfil\eject
+
+\def\runninghead{APPENDIX A --- FINAL DOCUMENT}
+
+And here's what the same excerpt looks like when typeset.
+
+\M{12}Procedure \PB{\\{prime\_the\_change\_buffer}}
+sets \PB{\\{change\_buffer}} in preparation for the next matching operation.
+Since blank lines in the change file are not used for matching, we have
+\PB{$(\\{change\_limit}\E\\{change\_buffer}\W\R\\{changing})$} if and only if
+the change file is exhausted. This procedure is called only when
+\PB{\\{changing}} is 1; hence error messages will be reported correctly.
+
+\Y\B\&{void} \\{prime\_the\_change\_buffer}(\,)\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{change\_limit}\K\\{change\_buffer}{}$;\C{ this value is used if the
+change file ends }\6
+\X13:Skip over comment lines in the change file; \PB{\&{return}} if end of file%
+\X;\6
+\X14:Skip to the next nonblank line; \PB{\&{return}} if end of file\X;\6
+\X15:Move \PB{\\{buffer}} and \PB{\\{limit}} to \PB{\\{change\_buffer}} and %
+\PB{\\{change\_limit}}\X;\6
+\4${}\}{}$\2\par
+\fi
+
+\M{13}While looking for a line that begins with \.{@x} in the change file, we
+allow lines that begin with \.{@}, as long as they don't begin with \.{@y},
+\.{@z}, or \.{@i} (which would probably mean that the change file is fouled up).
+
+\Y\B\4\X13:Skip over comment lines in the change file; \PB{\&{return}} if end
+of file\X${}\E{}$\6
+\&{while} (\T{1})\5
+${}\{{}$\1\6
+${}\\{change\_line}\PP;{}$\6
+\&{if} ${}(\R\\{input\_ln}(\\{change\_file})){}$\1\5
+\&{return};\2\6
+\&{if} ${}(\\{limit}<\\{buffer}+\T{2}){}$\1\5
+\&{continue};\2\6
+\&{if} ${}(\\{buffer}[\T{0}]\I\.{'@'}){}$\1\5
+\&{continue};\2\6
+\&{if} (\\{xisupper}(\\{buffer}[\T{1}]))\1\5
+${}\\{buffer}[\T{1}]\K\\{tolower}(\\{buffer}[\T{1}]);{}$\2\6
+\&{if} ${}(\\{buffer}[\T{1}]\E\.{'x'}){}$\1\5
+\&{break};\2\6
+\&{if} ${}(\\{buffer}[\T{1}]\E\.{'y'}\V\\{buffer}[\T{1}]\E\.{'z'}\V\\{buffer}[%
+\T{1}]\E\.{'i'}){}$\5
+${}\{{}$\1\6
+${}\\{loc}\K\\{buffer}+\T{2};{}$\6
+\\{err\_print}(\.{"!\ Missing\ @x\ in\ cha}\)\.{nge\ file"});\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\U12.\fi
+
+\M{14}Here we are looking at lines following the \.{@x}.
+
+\Y\B\4\X14:Skip to the next nonblank line; \PB{\&{return}} if end of file\X${}%
+\E{}$\6
+\&{do}\5
+${}\{{}$\1\6
+${}\\{change\_line}\PP;{}$\6
+\&{if} ${}(\R\\{input\_ln}(\\{change\_file})){}$\5
+${}\{{}$\1\6
+\\{err\_print}(\.{"!\ Change\ file\ ended}\)\.{\ after\ @x"});\6
+\&{return};\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\5
+\&{while} ${}(\\{limit}\E\\{buffer}){}$;\par
+\U12.\fi
+
+\M{15}\B\X15:Move \PB{\\{buffer}} and \PB{\\{limit}} to \PB{\\{change\_buffer}}
+and \PB{\\{change\_limit}}\X${}\E{}$\6
+${}\{{}$\1\6
+${}\\{change\_limit}\K\\{change\_buffer}-\\{buffer}+\\{limit};{}$\6
+${}\\{strncpy}(\\{change\_buffer},\39\\{buffer},\39\\{limit}-\\{buffer}+%
+\T{1});{}$\6
+\4${}\}{}$\2\par
+\Us12\ET16.\fi
+
+\vfil\eject\titletrue
+\rightskip=0pt % get out of C mode (cf. \B)
+\sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
+
+\def\runninghead{APPENDIX B --- MACROS FOR FORMATTING}
+\section Appendix B: The \.{cwebmac.tex} file.
+This is the file that extends ``plain \TEX/'' format in order to support the
+features needed by the output of \.{CWEAVE}.
+
+\vskip6pt
+\begingroup \def\tt{\eighttt} \baselineskip9pt
+\def\printmacs{\begingroup
+ \def\do##1{\catcode`##1=12 } \dospecials
+ \parskip 0pt \parindent 0pt
+ \catcode`\ =13 \catcode`\^^M=13
+ \tt \verbatimdefs \input cwebmac \endgroup}
+\printmacs
+\endgroup
+\vfill\eject
+
+\def\runninghead{APPENDIX C --- NOTES ON FORMATTING}
+\section Appendix C: How to use \.{CWEB} macros.
+The macros in \.{cwebmac} make it possible to produce a variety of formats
+without editing the output of \.{CWEAVE}, and the purpose of this appendix
+is to explain some of the possibilities.
+
+\def\point#1.{\yskip\indent#1.\quad\ignorespaces}
+
+\point 1. Four fonts have been declared in addition to the standard fonts of
+\.{PLAIN} format: You can say `\.{\{\\mc UNIX\}}' to get {\mc UNIX} in
+medium-size caps; you can say `\.{\{\\sc STUFF\}}' to get {\sc STUFF}
+in small caps; and you can select the largish fonts \.{\\titlefont}
+and \.{\\ttitlefont} in the title of your document, where \.{\\ttitlefont}
+is a typewriter style of type. There are macros \.{\\UNIX/} and \.{\\CEE/}
+to refer to \UNIX/ and \CEE/ with medium-size caps.
+
+\point 2. When you mention an identifier in \TEX/ text, you normally call
+it `\.{|identifier|}'. But you can also say `\.{\\\\\{identifier\}}'. The
+output will look the same in both cases, but the second alternative
+doesn't put \\{identifier} into the index, since
+it bypasses \.{CWEAVE}'s translation from \CEE/ mode. In the second
+case you must put a backslash before each underline character
+in the identifier.
+
+\point 3. To get typewriter-like type, as when referring to `\.{CWEB}', you
+can use the `\.{\\.}' macro (e.g., `\.{\\.\{CWEB\}}'). In the argument to
+this macro you should insert an additional backslash before the symbols
+listed as `special string characters' in the index to \.{CWEAVE}, i.e.,
+before backslashes and dollar signs and the like.
+A `\.{\\\ }' here will result in the visible space symbol; to get an
+invisible space following a control sequence you can say `\.{\{\ \}}'.
+If the string is long, you can break it up into substrings that
+are separated by `\.{\\)}'\,; the latter gives a discretionary backslash
+if \TEX/ has to break a line here.
+
+\point 4. The three control sequences \.{\\pagewidth}, \.{\\pageheight},
+and \.{\\fullpageheight} can be redefined in the limbo section at the
+beginning of your \.{CWEB} file, to change the dimensions of each page.
+The default settings
+$$\lpile{\.{\\pagewidth=6.5in}\cr
+ \.{\\pageheight=8.7in}\cr
+ \.{\\fullpageheight=9in}\cr}$$
+were used to prepare this manual; \.{\\fullpageheight} is
+\.{\\pageheight} plus room for the additional heading and page numbers at
+the top of each page. If you change any of these quantities, you should
+call the macro \.{\\setpage} immediately after making the change.
+
+\point 5. The \.{\\pageshift} macro defines an amount by which right-hand
+pages (i.e., odd-numbered pages) are shifted right with respect to
+left-hand (even-numbered) ones. By adjusting this amount you may be
+able to get two-sided output in which the page numbers line up on
+opposite sides of each sheet.
+
+\point 6. The \.{\\title} macro will appear at the top of each page
+in small caps; it is the job name unless redefined.
+
+\point 7. The first page usually is assigned page
+number 1. To start on page 16, with contents
+on page 15, say this: `\.{\\def\\contentspagenumber\{15\}}
+\.{\\pageno=\\contentspagenumber} \.{\\advance\\pageno by 1}'.
+
+\point 8. The macro \.{\\iftitle} will suppress the header line if it is
+defined by `\.{\\titletrue}'. The normal value is \.{\\titlefalse}
+except for the table of contents; thus, the contents
+page is usually unnumbered.
+
+Two macros are provided to give flexibility to the table of
+contents: \.{\\topofcontents} is invoked just before the contents
+info is read, and \.{\\botofcontents} is invoked just after.
+Here's a typical definition:
+$$\lpile{\.{\\def\\topofcontents\{\\null\\vfill}\cr
+ \.{ { }\\titlefalse \% include headline on the contents page}\cr
+ \.{ { }\\def\\rheader\{\\mainfont The \{\\tt CWEAVE\}{ }processor\\hfil\}}\cr
+ \.{ { }\\centerline\{\\titlefont The \{\\ttitlefont CWEAVE\}{ }processor\}}\cr
+ \.{ { }\\vskip 15pt \\centerline\{(Version 3.64)\}{ }\\vfill\}}\cr}$$
+Redefining \.{\\rheader}, which is the headline for right-hand pages,
+suffices in this case to put the desired information at the top of the
+contents page.
+
+\point 9. Data for the table of contents is written to a file that
+is read after the indexes have been \TEX/ed; there's one line of data
+for every starred section. The file \.{common.toc} might look like this:
+$$\lpile{\.{\\ZZ \{Introduction\}\{0\}\{1\}\{28\}\{\}}\cr
+ \.{\\ZZ \{The character set\}\{2\}\{5\}\{29\}\{\}}\cr}$$
+and so on. The \.{\\topofcontents} macro could
+redefine \.{\\ZZ} so that the information appears in any desired format.
+(See also point~19 below.)
+
+\point 10. Sometimes it is necessary or desirable to divide the output of
+\.{CWEAVE} into subfiles that can be processed separately. For example,
+the listing of \TEX/ runs to more than 500 pages, and that is enough to
+exceed the capacity of many printing devices and/or their software.
+When an extremely large job isn't cut into smaller pieces, the entire
+process might be spoiled by a single error of some sort, making it
+necessary to start everything over.
+
+Here's a safe way to break a woven file into three parts:
+Say the pieces are $\alpha$,
+$\beta$, and $\gamma$, where each piece begins with a starred section.
+All macros should be defined in the opening limbo section of $\alpha$,
+and copies of this \TEX/ code should be placed at the
+beginning of $\beta$ and of $\gamma$. In order to process the parts
+separately, we need to take care of two things: The starting page
+numbers of $\beta$ and $\gamma$ need to be set up properly, and
+the table of contents data from all three runs needs to be
+accumulated.
+
+The \.{cwebmac} macros include two control sequences \.{\\contentsfile} and
+\.{\\readcontents} that facilitate the necessary processing. We include
+`\.{\\def\\contentsfile\{cont1\}}' in the limbo section of $\alpha$, and
+we include `\.{\\def\\contentsfile\{cont2\}}' in the limbo section of
+$\beta$; this causes \TEX/ to write the contents data for $\alpha$ and $\beta$
+into \.{cont1.tex} and \.{cont2.tex}. Now in $\gamma$ we say
+$$\.{\\def\\readcontents\{\\input cont1 \\input cont2
+ \\input \\contentsfile\}}\,;$$
+this brings in the data from all three pieces, in the proper order.
+
+However, we still need to solve the page-numbering problem. One way to
+do it is to include the following in the limbo material for $\beta$:
+$$\lpile{\.{\\message\{Please type the last page number of part 1: \}}\cr
+ \.{\\read -1 to \\temp \\pageno=\\temp \\advance\\pageno by 1}\cr}$$
+Then you simply provide the necessary data when \TEX/ requests
+it; a similar construction is used at the beginning of $\gamma$.
+
+This method can, of course, be used to divide a woven file into
+any number of pieces.
+
+\point 11. Sometimes it is nice to include things in the index that are
+typeset in a special way. For example, we might want to have an
+index entry for `\TeX'. \.{CWEAVE} provides two simple ways to
+typeset an index entry (unless the entry is an identifier or a reserved word):
+`\.{@\^}' gives roman type, and `\.{@.}' gives typewriter type.
+But if we try to typeset `\TeX' in roman type by saying, e.g.,
+`\.{@\^\\TeX@>}', the backslash character gets in the way,
+and this entry wouldn't appear in the index with the T's.
+
+The solution is to use the `\.{@:}' feature, declaring a macro that
+simply removes a sort key as follows:
+$$\.{\\def\\9\#1\{\}}$$
+Now you can say, e.g., `\.{@:TeX\}\{\\TeX@>}' in your \.{CWEB} file; \.{CWEAVE}
+puts it into the index alphabetically, based on the sort key, and
+produces the macro call `\.{\\9\{TeX\}\{\\TeX\}}' which will ensure that
+the sort key isn't printed.
+
+A similar idea can be used to insert hidden material into section
+names so that they are alphabetized in whatever way you might wish.
+Some people call these tricks ``special refinements''; others call
+them ``kludges.''
+
+\point 12. The control sequence \.{\\secno} is set to the number of the
+section being typeset.
+
+\point 13. If you want to list only the sections that have changed,
+together with the index, put the command `\.{\\let\\maybe=\\iffalse}' in
+the limbo section before the first section of your \.{CWEB} file. It's
+customary to make this the first change in your change file.
+
+This feature has a \TeX nical limitation, however: You cannot use it
+together with control sequences like \.{\\proclaim} or \.{\\+} or
+\.{\\newcount} that plain \TeX\ has declared to be `\.{\\outer}',
+because \TeX\ refuses to skip silently over such control sequences.
+One way to work around this limitation is to say
+$$\.{\\fi \\let\\proclaim\\relax \\def\\proclaim\{...\} \\ifon}$$
+where \.{\\proclaim} is redefined to be the same as usual but without
+an \.{\\outer} qualification. (The \.{\\fi} here stops the conditional
+skipping, and the \.{\\ifon} turns it back on again.) Similarly,
+$$\.{\\fi \\newcount\\n \\ifon}$$
+is a safe way to use \.{\\newcount}. Plain \TeX\ already provides a
+non-outer macro \.{\\tabalign} that does the work of \.{\\+}; you can say
+$$\postdisplaypenalty=10000
+\.{\\fi \\let\\+\\tabalign \\ifon}$$
+if you prefer the shorter notation \.{\\+}.
+
+\point 14. To get output in languages other than English, redefine the
+macros \.{\\A}, \.{\\As}, \.{\\ET}, \.{\\ETs}, \.{\\Q}, \.{\\Qs}, \.{\\U},
+\.{\\Us}, \.{\\ch}, \.{\\fin}, \.{\\con}, \.{\\today}, \.{\\datethis}, and
+\.{\\datecontentspage}. \.{CWEAVE} itself need not be changed.
+
+\point 15. Some output can be selectively suppressed with the macros
+\.{\\noatl}, \.{\\noinx}, \.{\\nosecs}, \.{\\nocon}.
+
+\point 16. All accents and special text symbols of plain \TEX/ format
+will work in \.{CWEB} documents just as they are described in
+Chapter~9 of {\sl The \TEX/book}, with one exception.
+The dot accent (normally \.{\\.}) must be typed \.{\\:} instead.
+
+\point 17. Several commented-out lines in \.{cwebmac.tex} are suggestions
+that users may wish to adopt. For example, one such line inserts a blank page
+if you have a duplex printer. Appendices D, E, and F of the complete
+version of this manual are printed using a commented-out option that
+substitutes `$\gets$' for `$=$' in the program listings. Looking at those
+appendices might help you decide which format you like better.
+
+\point 18. Andreas Scherer has contributed a macro called \.{\\pdfURL}
+with which one can say things like the following, anywhere in the \TeX\ parts
+or the \CEE/ comments of a \.{CWEB} file:
+$$\vbox{\halign{\.{#}\hfil\cr
+You can send email to
+ \\pdfURL\{the author\}\{mailto:andreas.scherer@@pobox.com\}\cr
+or visit \\pdfURL\{his home page\}\{http://www.pobox.com/%
+ \\TILDE/scherer\}.\cr}}$$
+In a {\mc PDF} document, the first argument will appear in blue as
+clickable text; the Acrobat reader, if correctly configured, will then
+redirect those links to the user's browser and open either the
+email client or the HTML viewer. In a hardcopy document, both arguments
+will be printed ({\tt the second in parentheses and typewriter type}).
+Certain special characters in an Internet address need to be handled
+in a somewhat awkward way, so that \.{CWEAVE} and/or \TeX\
+will not confuse them with formatting controls: Use \.{@@} for \.@
+and \.{\\TILDE/} for \.\~ and \.{\\UNDER/} for \.\_.
+
+\point 19. {\mc PDF} documents contain bookmarks that list all the major group
+titles in the table of contents, some of which will be subsidiary to
+others if the depth feature of \.{@*} has been used.
+Such bookmark entries are also known as ``outlines.''
+Moreover, the final group title, `Names of the sections',
+can be opened up to list every section name; Acrobat users can therefore
+navigate easily to any desired section.
+
+The macros of \.{cwebmac.tex} are careful to ``sanitize'' all the names
+that appear as bookmarks, by removing special characters and
+formatting codes that are inappropriate for the limited typographic
+capabilities of {\mc PDF} outlines. For example, one section of \.{CWEAVE}
+is named `Cases for \\{case\_like}', which is represented by the \TeX\ code
+`\.{Cases} \.{for} \.{\\PB\{\\\\\{case\\\_like\}\}}' in \.{cweave.tex}; its
+sanitized name is simply `\.{Cases} \.{for} \.{case\_like}'.
+(When \.{.pdf} files are produced, the fifth parameter of every \.{\\ZZ} in
+the \.{.toc} file is set to the sanitized form of the first parameter;
+see point~9 above and point~20 below.)
+
+In general, sanitization removes \TeX\ control sequences and braces,
+except for control sequences defined by \.{CWEB} itself. Such a translation
+works most of the time, but you can override the defaults and obtain any
+translation that you want by using \TeX nical tricks. For example, after
+$$\.{\\sanitizecommand\\foo\{bar\}}$$
+the control sequence \.{\\foo} will sanitize to `\.{bar}'. And after
+$$\.{\\def\\kluj\#1\\\\\{foo\}}$$
+the \TeX\ code `\.{\\kluj bar\\\\}' will print as `foo' but sanitize
+to `\.{bar}', because the control sequences \.{\\kluj} and
+\.{\\\\} are removed by sanitization.
+
+\point 20. Furthermore, group titles can be converted to an arbitrary
+sanitized text while also changing their form in running headlines, by
+using \.{\\ifheader}. Consider, for example, a \.{CWEB} source file that
+begins with the two lines
+$$\lpile{\.{\\def\\klujj\#1\\\\\{\\ifheader FOO\\else foo\\fi\}}\cr
+\.{@*Chinese \\klujj bar\\.}\cr}$$
+This coding introduces a major group entitled `{\bf Chinese foo}', with
+running headline `{\eightrm CHINESE FOO}' and table-of-contents entry
+`Chinese foo'. The corresponding bookmark is, however, `\.{Chinese} \.{bar}'.
+And the corresponding \.{.toc} file entry is
+`\.{\\ZZ \{Chinese \\klujj bar\\\\\}\{1\}\{1\}\{1\}\{Chinese bar\}}'.
+
+\vfill\end
+
diff --git a/Build/source/texk/web2c/cwebdir/depend.mak b/Build/source/texk/web2c/cwebdir/depend.mak
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/depend.mak
diff --git a/Build/source/texk/web2c/cwebdir/makefile.bs b/Build/source/texk/web2c/cwebdir/makefile.bs
new file mode 100644
index 00000000000..5e970128049
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/makefile.bs
@@ -0,0 +1,60 @@
+# Makefile for CTANGLE and CWEAVE, pc/big versions, using
+# Borland C++ 3.1 and Borland Make.
+#
+# (This file contributed by Barry Schwartz, trashman@crud.mn.org,
+# 24 Jul 94.)
+
+
+
+CC = bcc
+
+# Redundant Load Suppression (-Z) is turned off, because it seems to
+# break the code. Likewise for Copy Propagation (-Op). (These
+# optimizations don't seem to cause any problems in common.w, but
+# better safe than sorry--compile everything with them turned off.)
+OPT = -O2-p -Z-
+
+# Compile with symbols. That way you'll be able to use the debugger if
+# you run into trouble. You can always use tdstrip later, to remove the
+# symbols.
+DEBUG = -v
+
+LCFLAGS = -mc -Ff=5000 -d -w-pro $(DEBUG)
+CFLAGS = $(LCFLAGS) $(OPT)
+COMPILE = $(CC) $(CFLAGS)
+
+LINK = $(CC) $(LCFLAGS) -e
+
+
+
+# Where to find an "old" version of ctangle, for bootstrapping. The first
+# time you make ctangle, you may have to edit the distributed ctangle.c
+# and/or common.c by hand to reduce the size of one or more arrays.
+# This will give you a functional ctangle.exe, which you can use to bootstrap
+# the "real" ctangle.exe.
+CTANGLE = ctangle
+
+
+
+
+all default: ctangle.exe cweave.exe
+
+
+ctangle.exe: ctangle.obj common.obj
+ $(LINK)$* $**
+
+cweave.exe: cweave.obj common.obj
+ $(LINK)$* $**
+
+
+common.obj: common.w comm-bs.ch
+ $(CTANGLE) common.w comm-bs.ch
+ $(COMPILE) -c common.c
+
+ctangle.obj: ctangle.w common.h ctang-bs.ch
+ $(CTANGLE) ctangle.w ctang-bs.ch
+ $(COMPILE) -c ctangle.c
+
+cweave.obj: cweave.w common.h cweav-bs.ch
+ $(CTANGLE) cweave.w cweav-bs.ch
+ $(COMPILE) -c cweave.c
diff --git a/Build/source/texk/web2c/cwebdir/prod.w b/Build/source/texk/web2c/cwebdir/prod.w
new file mode 100644
index 00000000000..5f76a193794
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/prod.w
@@ -0,0 +1,307 @@
+% This file is part of CWEB.
+% This program by Silvio Levy and Donald E. Knuth
+% is based on a program by Knuth.
+% It is distributed WITHOUT ANY WARRANTY, express or implied.
+% Version 3.6 --- May 2000
+%
+@ Here is a table of all the productions. Each production that
+combines two or more consecutive scraps implicitly inserts a {\tt \$}
+where necessary, that is, between scraps whose abutting boundaries
+have different |mathness|. In this way we never get double {\tt\$\$}.
+
+% The following kludge is needed because \newcount, \newdimen, and \+
+% are "\outer" control sequences that cannot be used in skipped text!
+\fi \newcount\prodno \newdimen\midcol \let\+\relax \ifon
+
+\def\v{\char'174}
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+
+A translation is provided when the resulting scrap is not merely a
+juxtaposition of the scraps it comes from. An asterisk$^*$ next to a scrap
+means that its first identifier gets an underlined entry in the index,
+via the function |make_underlined|. Two asterisks$^{**}$ means that both
+|make_underlined| and |make_reserved| are called; that is, the
+identifier's ilk becomes |raw_int|. A dagger \dag\ before the
+production number refers to the notes at the end of this section,
+which deal with various exceptional cases.
+
+We use \\{in}, \\{out}, \\{back} and
+\\{bsp} as shorthands for |indent|, |outdent|, |backup| and
+|break_space|, respectively.
+
+\begingroup \lineskip=4pt
+\def\alt #1 #2
+{$\displaystyle\Bigl\{\!\matrix{\strut\hbox{#1}\cr
+ \strut\hbox{#2}\cr}\!\Bigr\}$ }
+\def\altt #1 #2 #3
+{$\displaystyle\Biggl\{\!\matrix{\strut\hbox{#1}\cr\hbox{#2}\cr
+ \strut\hbox{#3}\cr}\!\Biggr\}$ }
+\def\malt #1 #2
+{$\displaystyle\matrix{\strut\hbox{#1}\hfill\cr\strut\hbox{#2}\hfill\cr}$}
+\def\maltt #1 #2 #3
+{$\displaystyle\matrix{\strut\hbox{#1}\hfill\cr\hbox{#2}\hfill\cr
+ \strut\hbox{#3}\hfill\cr}$}
+\yskip
+\prodno=0 \midcol=2.5in
+\def\theprodno{\number\prodno \global\advance\prodno by1\enspace}
+\def\dagit{\dag\theprodno}
+\def\+#1&#2&#3&#4\cr{\def\next{#1}%
+ \line{\hbox to 2em{\hss
+ \ifx\next\empty\theprodno\else\next\fi}\strut
+ \ignorespaces#2\hfil\hbox to\midcol{$\RA$
+ \ignorespaces#3\hfil}\quad \hbox to1.45in{\ignorespaces#4\hfil}}}
+\+\relax & LHS & RHS \hfill Translation & Example\cr
+\yskip
+\+& \altt\\{any} {\\{any} \\{any}} {\\{any} \\{any} \\{any}}
+|insert| & \altt\\{any} {\\{any} \\{any}} {\\{any} \\{any} \\{any}}
+& stmt; \ /$\ast\,$comment$\,*$/\cr
+\+& |exp| \altt|lbrace| |int_like| |decl|
+ & |fn_decl| \altt|lbrace| |int_like| |decl|
+ \hfill $F=E^*\,|in|\,|in|$ & \malt {\\{main}()$\{$}
+ {\\{main}$(\\{ac},\\{av})$ \&{int} \\{ac};} \cr
+\+& |exp| |unop| & |exp| & |x++|\cr
+\+& |exp| \alt |binop| |ubinop| |exp| & |exp| & \malt {|x/y|} {|x+y|} \cr
+\+& |exp| |comma| |exp| & |exp| \hfill $EC\,|opt|9\,E$& |f(x,y)|\cr
+\+& |exp| \alt {|lpar| |rpar|} |cast| |colon| &
+ |exp| \alt {|lpar| |rpar|} |cast| |base| &
+ \malt \&C|()|: {\&C|int i)|:} \cr
+\+& |exp| |semi| & |stmt| & |x=0;|\cr
+\+& |exp| |colon| & |tag| \hfill $E^*C$ & |found:|\cr
+\+& |exp| |rbrace| & |stmt| |rbrace| & end of \&{enum} list\cr
+\+& |exp| \alt {|lpar| |rpar|} |cast| \alt|const_like| |case_like| &
+ |exp| \alt {|lpar| |rpar|} |cast| \hfill
+ \alt $R=R\.\ C$ $C_1=C_1\.\ C_2$ &
+ \malt {|f() const|} {|f(int) throw|} \cr
+\+& |exp| \alt |exp| |cast| & |exp| & |time()|\cr
+\+& |lpar| \alt |exp| |ubinop| |rpar| & |exp| & \malt{|(x)|} {|(*)|} \cr
+\+& |lpar| |rpar| & |exp| \hfill $L\.{\\,}R$ & functions, declarations\cr
+\+& |lpar| \altt |decl_head| |int_like| |cast| |rpar| & |cast| & |(char*)|\cr
+\+& |lpar| \altt |decl_head| |int_like| |exp| |comma| & |lpar| \hfill
+ $L$\,\altt $D$ $I$ $E$ $C$\,|opt|9 & |(int,|\cr
+\+& |lpar| \alt |stmt| |decl| & |lpar| \hfill \alt {$LS\.\ $} {$LD\.\ $} &
+ \malt {|(k=5;|} {|(int k=5;|} \cr
+\+& |unop| \alt |exp| |int_like| & |exp| &
+ \malt |!x| |~|\&C \cr
+\+& |ubinop| |cast| |rpar| & |cast| |rpar| \hfill
+ $C=\.\{U\.\}C$ & |*|\&{CPtr}) \cr
+\+& |ubinop| \alt|exp| |int_like| & \alt|exp| |int_like| \hfill
+ \.\{$U$\.\}\alt$E$ $I$ & \malt |*x| |*|\&{CPtr} \cr
+\+& |ubinop| |binop| & |binop| \hfill $|math_rel|\,U\.\{B\.\}\.\}$ & |*=|\cr
+\+& |binop| |binop| & |binop| \hfill
+ $|math_rel|\,\.\{B_1\.\}\.\{B_2\.\}\.\}$ & |>>=|\cr
+\+& |cast| \alt |lpar| |exp| & \alt |lpar| |exp| \hfill
+ \alt $CL$ $C\.\ E$ & \malt |(double)(x+2)| |(double)x| \cr
+\+& |cast| |semi| & |exp| |semi| & |(int);|\cr
+\+& |sizeof_like| |cast| & |exp| & |sizeof (double)|\cr
+\+& |sizeof_like| |exp| & |exp| \hfill $S\.\ E$ & |sizeof x|\cr
+\+& |int_like| \alt|int_like| |struct_like| &
+ \alt|int_like| |struct_like| \hfill $I\.\ $\alt $I$ $S$
+ \unskip& |extern char|\cr
+\+& |int_like| |exp| \alt|raw_int| |struct_like| &
+ |int_like| \alt|raw_int| |struct_like| & |extern "Ada" int|\cr
+\+& |int_like| \altt|exp| |ubinop| |colon| &
+ |decl_head| \altt|exp| |ubinop| |colon| \hfill
+ $D=I$\.\ & \maltt|int x| |int*x| |unsigned:| \cr
+\+& |int_like| \alt |semi| |binop| & |decl_head| \alt |semi| |binop| &
+ \malt |int x;| {\&{int} $f(\&{int}=4)$} \cr
+\+& |public_like| |colon| & |tag| & \&{private}:\cr
+\+& |public_like| & |int_like| & \&{private}\cr
+\+& |colcol| \alt|exp| |int_like| & \alt|exp| |int_like| \hfill
+ |qualifier| $C$ \alt$E$ $I$ & \&C\DC$x$\cr
+\+& |colcol| |colcol| & |colcol| & \&C\DC\&B\DC\cr
+\+& |decl_head| |comma| & |decl_head| \hfill $DC\.\ $ & |int x,|\cr
+\+& |decl_head| |ubinop| & |decl_head| \hfill $D\.\{U\.\}$ & |int *|\cr
+\+\dagit& |decl_head| |exp| & |decl_head| \hfill $DE^*$ & |int x|\cr
+\+& |decl_head| \alt|binop| |colon| |exp| \altt|comma| |semi| |rpar| &
+ |decl_head| \altt|comma| |semi| |rpar| \hfill
+ $D=D$\alt $B$ $C$ \unskip$E$ & \malt {\&{int} $f(\&{int}\ x=2)$} |int b:1| \cr
+\+& |decl_head| |cast| & |decl_head| & |int f(int)|\cr
+\+& |decl_head| \altt|int_like| |lbrace| |decl| & |fn_decl|
+ \altt|int_like| |lbrace| |decl| \hfill $F=D\,|in|\,|in|$
+ & |long time () {|\cr
+\+& |decl_head| |semi| & |decl| & |int n;|\cr
+\+& |decl| |decl| & |decl| \hfill $D_1\,|force|\,D_2$ & |int n;double x;|\cr
+\+& |decl| \alt|stmt| |function| & \alt|stmt| |function|
+ \hfill $D\,|big_force|\,$\alt $S$ $F$ \unskip& \&{extern} $n$;
+ \\{main} ()|{}|\cr
+\+& |base| \alt |int_like| |exp| |comma| & |base| \hfill
+ $B$\.\ \alt $I$ $E$ \unskip$C$\,|opt|9
+ & \malt {: \&{public} \&A,} {: $i(5)$,} \cr
+\+& |base| \alt |int_like| |exp| |lbrace| & |lbrace| \hfill
+ $B$\.\ \alt $I$ $E$ \unskip\.\ $L$ & \&D : \&{public} \&A $\{$\cr
+\+& |struct_like| |lbrace| & |struct_head| \hfill $S\.\ L$ & |struct {|\cr
+\+& |struct_like| \alt|exp| |int_like| |semi| & |decl_head| |semi|
+ \hfill $S\.\ $\alt $E^{**}$ $I^{**}$ & \&{struct} \&{forward};\cr
+\+& |struct_like| \alt|exp| |int_like| |lbrace| & |struct_head| \hfill
+ $S\.\ $\alt $E^{**}$ $I^{**}$ \unskip $\.\ L$ &
+ \&{struct} \&{name\_info} $\{$\cr
+\+& |struct_like| \alt|exp| |int_like| |colon| &
+ |struct_like| \alt|exp| |int_like| |base| & |class| \&C :\cr
+\+\dagit& |struct_like| \alt|exp| |int_like| & |int_like|
+ \hfill $S\.\ $\alt$E$ $I$ & \&{struct} \&{name\_info} $z$;\cr
+\+& |struct_head| \altt|decl| |stmt| |function| |rbrace| & |int_like|\hfill
+ $S\,\\{in}\,|force|$\altt$D$ $S$ $F$ $\\{out}\,|force|\,R$ &
+ |struct {| declaration |}|\cr
+\+& |struct_head| |rbrace| & |int_like|\hfill $S\.{\\,}R$ & |class C{}|\cr
+\+& |fn_decl| |decl| & |fn_decl| \hfill $F\,|force|\,D$
+ & $f(z)$ \&{double} $z$; \cr
+\+& |fn_decl| |stmt| & |function| \hfill $F\,|out|\,|out|\,|force|\,S$
+ & \\{main}() {\dots}\cr
+\+& |function| \altt|stmt| |decl| |function| & \altt |stmt| |decl| |function|
+ \hfill $F\,|big_force|\,$\altt $S$ $D$ $F$ & outer block\cr
+\+& |lbrace| |rbrace| & |stmt| \hfill $L\.{\\,}R$ & empty statement\cr
+\advance\midcol35pt
+\+& |lbrace| \altt|stmt| |decl| |function| |rbrace| & |stmt| \hfill
+ $|force|\,L\,\\{in}\,|force|\,S\,
+ |force|\,\\{back}\,R\,\\{out}\,|force|$ & compound statement\cr
+\advance\midcol-20pt
+\+& |lbrace| |exp| [|comma|] |rbrace| & |exp| & initializer\cr
+\+& |if_like| |exp| & |if_clause| \hfill $I\.{\ }E$ & |if (z)|\cr
+\+& |else_like| |colon| & |else_like| |base| & \&{try} :\cr
+\+& |else_like| |lbrace| & |else_head| |lbrace| & \&{else} $\{$\cr
+\+& |else_like| |stmt| & |stmt| \hfill
+ $|force|\,E\,\\{in}\,\\{bsp}\,S\,\\{out}\,|force|$ & |else x=0;|\cr
+\+& |else_head| \alt|stmt| |exp| & |stmt| \hfill
+ $|force|\,E\,\\{bsp}\,|noop|\,|cancel|\,S\,\\{bsp}$ & |else{x=0;}|\cr
+\+& |if_clause| |lbrace| & |if_head| |lbrace| & |if (x) {|\cr
+\+& |if_clause| |stmt| |else_like| |if_like| & |if_like| \hfill
+ $|force|\,I\,\\{in}\,\\{bsp}\,S\,\\{out}\,|force|\,E\,\.\ I$ &
+ |if (x) y; else if|\cr
+\+& |if_clause| |stmt| |else_like| & |else_like| \hfill
+ $|force|\,I\,\\{in}\,\\{bsp}\,S\,\\{out}\,|force|\,E$ &
+ |if (x) y; else|\cr
+\+& |if_clause| |stmt| & |else_like| |stmt| & |if (x)|\cr
+\+& |if_head| \alt|stmt| |exp| |else_like| |if_like| & |if_like| \hfill
+ $|force|\,I\,\\{bsp}\,|noop|\,|cancel|\,S\,|force|\,E\,\.\ I$ &
+ |if (x){y;}else if|\cr
+\+& |if_head| \alt|stmt| |exp| |else_like| & |else_like| \hfill
+ $|force|\,I\,\\{bsp}\,|noop|\,|cancel|\,S\,|force|\,E$ &
+ |if (x){y;}else|\cr
+\+& |if_head| \alt|stmt| |exp| & |else_head| \alt|stmt| |exp| & |if (x){y;}|\cr
+\advance\midcol20pt
+\+& |do_like| |stmt| |else_like| |semi| & |stmt| \hfill
+ $D\,\\{bsp}\,|noop|\,|cancel|\,S\,|cancel|\,|noop|\,\\{bsp}\,ES$%
+ & |do f(x); while (g(x));|\cr
+\advance\midcol-20pt
+\+& |case_like| |semi| & |stmt| & |return;|\cr
+\+& |case_like| |colon| & |tag| & |default:|\cr
+\+& |case_like| |exp| & |exp| \hfill $C\.\ E$ & |return 0|\cr
+\+& |catch_like| \alt|cast| |exp| & |fn_decl| \hfill
+ $C$\alt $C$ $E$ \\{in}\,\\{in} & |catch (...)|\cr
+\+& |tag| |tag| & |tag| \hfill $T_1\,\\{bsp}\,T_2$ & |case 0: case 1:|\cr
+\+& |tag| \altt|stmt| |decl| |function| & \altt|stmt| |decl| |function|
+ \hfill $|force|\,\\{back}\,T\,\\{bsp}\,S$ & |case 0: z=0;|\cr
+\+\dagit& |stmt| \altt|stmt| |decl| |function| &
+ \altt|stmt| |decl| |function|
+ \hfill $S\,$\altt$|force|\,S$ $|big_force|\,D$ $|big_force|\,F$ &
+ |x=1;y=2;|\cr
+\+& |semi| & |stmt| \hfill \.\ $S$& empty statement\cr
+\+\dagit& |lproc| \altt |if_like| |else_like| |define_like| & |lproc| &
+ \maltt {{\bf \#include}} {\bf\#else} {\bf\#define} \cr
+\+& |lproc| |rproc| & |insert| & {\bf\#endif} \cr
+\+& |lproc| \alt {|exp| [|exp|]} |function| |rproc| & |insert| \hfill
+ $I$\.\ \alt {$E{[\.{\ \\5}E]}$} {$F$} &
+ \malt{{\bf\#define} $a$\enspace 1} {{\bf\#define} $a$\enspace$\{\,b;\,\}$} \cr
+\+& |section_scrap| |semi| & |stmt|\hfill $MS$ |force|
+ &$\langle\,$section name$\,\rangle$;\cr
+\+& |section_scrap| & |exp| &$\langle\,$section name$\,\rangle$\cr
+\+& |insert| |any| & |any| & \.{\v\#include\v}\cr
+\+& |prelangle| & |binop| \hfill \.< & $<$ not in template\cr
+\+& |prerangle| & |binop| \hfill \.> & $>$ not in template\cr
+\+& |langle| |prerangle| & |cast| \hfill $L\.{\\,}P$ & $\langle\,\rangle$\cr
+\+& |langle| \altt|decl_head| |int_like| |exp| |prerangle| & |cast| &
+ $\langle\&{class}\,\&C\rangle$\cr
+\+& |langle| \altt|decl_head| |int_like| |exp| |comma| & |langle| \hfill
+ $L$\,\altt $D$ $I$ $E$ $C$\,|opt|9 & $\langle\&{class}\,\&C,$\cr
+\+& |template_like| |exp| |prelangle| & |template_like| |exp| |langle| &
+ \&{template} $a\langle100\rangle$\cr
+\+& |template_like| \alt|exp| |raw_int| & \alt|exp| |raw_int| \hfill
+ $T$\.\ \alt$E$ $R$ & \&C\DC\&{template} |a()|\cr
+\+& |template_like| & |raw_int| & \&{template}$\langle\&{class}\,\&T\rangle$\cr
+\+& |new_like| |lpar| |exp| |rpar| & |new_like| & \&{new}(\\{nothrow})\cr
+\+& |new_like| |cast| & |exp| \hfill $N\.\ C$ & |new(int*)|\cr
+\+\dagit& |new_like| & |new_exp| & \&{new} \&C|()|\cr
+\+& |new_exp| \alt|int_like| |const_like| & |new_exp| \hfill
+ $N$\.\ \alt $I$ $C$ & |new const int|\cr
+\+& |new_exp| |struct_like| \alt |exp| |int_like| & |new_exp| \hfill
+ $N\.\ S$\.\ \alt $E$ $I$ & \&{new} \&{struct} \&S\cr
+\+& |new_exp| |raw_ubin| & |new_exp| \hfill $N\.\{R\.\}$ & |new int*[2]|\cr
+\+& |new_exp| \alt |lpar| |exp| & |exp| \alt |lpar| |exp| \hfill
+ $E=N$\,\alt {} {\.\ } & \malt |operator[](int)| {|new int(2)|} \cr
+\+\dagit& |new_exp| & |exp| & |new int;|\cr
+\+& |ftemplate| |prelangle| & |ftemplate| |langle| & |make_pair<int,int>|\cr
+\+& |ftemplate| & |exp| & |make_pair(1,2)|\cr
+\+& |for_like| |exp| & |else_like| \hfill $F\.\ E$ & |while (1)|\cr
+\+& |raw_ubin| |const_like| & |raw_ubin| \hfill $RC$\.{\\\ }
+ & $*$\&{const} |x|\cr
+\+& |raw_ubin| & |ubinop| & $*$ |x|\cr
+\+& |const_like| & |int_like| & \&{const} |x|\cr
+\+& |raw_int| |prelangle| & |raw_int| |langle| & \&C$\langle$\cr
+\+& |raw_int| |colcol| & |colcol| & \&C\DC\cr
+\+& |raw_int| |cast| & |raw_int| & \&C$\langle\&{class}\ \&T\rangle$\cr
+\+& |raw_int| |lpar| & |exp| |lpar| & \&{complex}$(x,y)$\cr
+\+\dagit& |raw_int| & |int_like| & \&{complex} |z|\cr
+\+\dagit& |operator_like| \altt|binop| |unop| |ubinop| & |exp|
+ \hfill $O$\.\{\altt $B$ $U$ $U$ \unskip\.\} & |operator+|\cr
+\+& |operator_like| \alt|new_like| |delete_like| & |exp| \hfill
+ $O$\.\ \alt $N$ $S$ & |operator delete|\cr
+\+& |operator_like| |comma| & |exp| & \&{operator},\cr
+\+\dagit& |operator_like| & |new_exp| & |operator char*|\cr
+\advance\midcol-8pt
+\+& |typedef_like| \alt|int_like| |cast| \alt|comma| |semi| &
+ |typedef_like| |exp| \alt|comma| |semi| & \&{typedef} \&{int} \&I,\cr
+\advance\midcol+8pt
+\+& |typedef_like| |int_like| & |typedef_like| \hfill $T\.\ I$ &
+ \&{typedef} \&{char}\cr
+\+\dagit& |typedef_like| |exp| & |typedef_like| \hfill $T\.\ E^{**}$ &
+ \&{typedef} \&I \.{@@[@@]} (|*|\&P)\cr
+\+& |typedef_like| |comma| & |typedef_like| \hfill $TC\.\ $ &
+ \&{typedef} \&{int} \&x,\cr
+\+& |typedef_like| |semi| & |decl| & \&{typedef} \&{int} $\&x,\&y$;\cr
+\+& |typedef_like| |ubinop| \alt |cast| |ubinop| &
+ |typedef_like| \alt |cast| |ubinop| \hfill
+ \alt $C=\.\{U\.\}C$ $U_2=\.\{U_1\.\}U_2$ \unskip &
+ \&{typedef} |*|{}|*|(\&{CPtr})\cr
+\+& |delete_like| |lpar| |rpar| & |delete_like|\hfill $DL\.{\\,}R$ &
+ \&{delete}|[]| \cr
+\+& |delete_like| |exp| & |exp| \hfill $D\.\ E$ & |delete p| \cr
+\+\dagit& |question| |exp| \alt |colon| |base| & |binop| &
+ \malt |?x:| |?f():| \cr
+\+& |begin_arg| |end_arg| & |exp| & \.{@@[}\&{char}$*$\.{@@]}\cr
+\+& |any_other| |end_arg| & |end_arg| & \&{char}$*$\.{@@]}\cr
+\yskip
+\yskip
+\yskip
+\parindent=0pt
+\dag{\bf Notes}
+\yskip
+Rule 35: The |exp| must not be immediately followed by |lpar|, |exp|,
+ or~|cast|.
+
+Rule 48: The |exp| or |int_like| must not be immediately followed by |base|.
+
+Rule 76: The |force| in the |stmt| line becomes \\{bsp} if \.{CWEAVE} has
+been invoked with the \.{-f} option.
+
+Rule 78: The |define_like| case calls |make_underlined| on the following scrap.
+
+Rule 94: The |new_like| must not be immediately followed by |lpar|.
+
+Rule 99: The |new_exp| must not be immediately followed by |raw_int|,
+|struct_like|, or |colcol|.
+
+Rule 110: The |raw_int| must not be immediately followed by |langle|.
+
+Rule 111: The operator after |operator_like|
+must not be immediately followed by a |binop|.
+
+Rule 114: The |operator_like| must not be immediately followed by
+|raw_ubin|.
+
+Rule 117: The |exp| must not be immediately followed by |lpar|, |exp|,
+or |cast|.
+
+Rule 123: The mathness of the |colon| or |base| changes to `yes'.
+
+\endgroup
diff --git a/Build/source/texk/web2c/cwebdir/readme.ql b/Build/source/texk/web2c/cwebdir/readme.ql
new file mode 100644
index 00000000000..907d4c3192b
--- /dev/null
+++ b/Build/source/texk/web2c/cwebdir/readme.ql
@@ -0,0 +1,84 @@
+This is the readme file for CWEB for QDOS/SMSQ systems
+
+(These instructions are for systems with Toolkit II,
+ please report any problems to me, the address is at the
+ end of the file)
+
+If you want to compile CWEB for your QL system, you must first
+convert the ASCII code to the QL's character set. Therefore you
+can use the little BASIC program appended at the end of the file.
+
+For a first version you have to alter the supplied ctangle_c file.
+Set your DATA_USE to the directory you have the CWEB sources in, and
+the PROG_USE to C68's directory.
+compile it with:
+ex cc;'common_c ctangle_c -bufp500K -octangle'
+
+then ctangle the source files with:
+ex datad$&'ctangle';'common_w comm-ql_ch'
+ex datad$&'ctangle';'ctangle_w ctang-ql_ch'
+ex datad$&'ctangle';'cweave_w cweav-ql_ch'
+
+Compile the following way (C68v4.14 +):
+
+ex cc;'-c common_c'
+ex cc;'-c ctangle_c'
+ex cc;'-c cweave_c'
+ex ld;'-bufp500K common_o ctangle_o -octangle'
+ex ld;'-bufp500K common_o cweave_o -ocweave'
+
+After that copy the ctangle and cweave executables into your
+programs directory (if you want them there).
+
+The DATA default may be used as usual. E.g. if you have
+a file win2_data_test_w and the DATA default set to
+win2_data_ you may call ctangle with
+ ex ctangle;'test'
+assuming that ctangle is in your PROG default.
+
+Please report any problems with the QL version to:
+Robert Klein
+Bluecherstrasse 24
+D-56349 Kaub
+Germany
+
+
+**************** ASCII Conversion program ***************
+With this program you can convert DOS and Unix 7-Bit ASCII
+files to the QL's character set. You'll need Toolkit II.
+The program will take all the files in the source directory
+and put them converted into the destination&source directory,
+e.g. you have as drive1$='win2_', drive2$='win3_',
+path1$='cweb_' and path2$='ql_'. Then the routine will take
+all files in win2_cweb_ (wthout subdirectories!) convert them
+and write them to 'win3_ql_cweb_'. It's only a lousy hack,
+but it'll do it's job.
+
+1000 DEFine PROCedure dos2ql (drive1$,path1$,drive2$,path2$)
+1002 LOCal zx$,zx%,ishl,ashl
+1005 DELETE drive2$&path2$&'dirlist'
+1010 OPEN_NEW#5,drive2$&path2$&'dirlist'
+1020 DIR#5,drive1$&path1$
+1030 CLOSE#5
+1040 OPEN_IN#5,drive2$&path2$&'dirlist'
+1050 INPUT#5,zx$:INPUT#5,zx$:REMark devicename and sectors
+1060 REPeat ashl
+1070 IF EOF(#5)THEN EXIT ashl
+1080 INPUT#5,zx$
+1085 IF '->' INSTR zx$ THEN NEXT ashl
+1090 OPEN_IN#3,drive1$&zx$
+1100 OPEN_NEW#4,drive2$&path2$&zx$
+1110 REPeat ishl
+1120 IF EOF(#3)THEN EXIT ishl
+1130 BGET#3,zx%
+1140 SELect ON zx%
+1150 = 13:REMark do nothing (DOS LineFeed)
+1155 = 26:REMark do nothing (DOS EOF sign)
+1160 = 96: BPUT#4,159:REMark Unix/DOS beginning quote sign
+1170 = REMAINDER : BPUT#4,zx%
+1180 END SELect
+1190 END REPeat ishl
+1195 CLOSE#3:CLOSE#4
+1200 END REPeat ashl
+1205 CLOSE#5
+1210 END DEFine dos2ql