summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/ctiedir
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/web2c/ctiedir
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/ctiedir')
-rw-r--r--Build/source/texk/web2c/ctiedir/ChangeLog119
-rw-r--r--Build/source/texk/web2c/ctiedir/Makefile51
-rw-r--r--Build/source/texk/web2c/ctiedir/README75
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie-k.ch727
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.155
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.c1111
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.cf114
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.cf226
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.cf313
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.chf.gen26
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.inc4
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.inc11
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.inc21
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.master.gen19
-rwxr-xr-xBuild/source/texk/web2c/ctiedir/ctie.test20
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.tie16
-rw-r--r--Build/source/texk/web2c/ctiedir/ctie.w1280
-rw-r--r--Build/source/texk/web2c/ctiedir/ctiedoc.tex242
18 files changed, 3800 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/ctiedir/ChangeLog b/Build/source/texk/web2c/ctiedir/ChangeLog
new file mode 100644
index 00000000000..74c3f1e9386
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ChangeLog
@@ -0,0 +1,119 @@
+2020-07-24 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Format types in boldface prior to their definition.
+
+2020-06-10 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: A few random finds while skimming the formatted code.
+
+2020-06-08 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Put 'date' at the bottom of table-of-contents page.
+
+2020-06-07 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Underscore 'enum'erated values in index.
+
+2020-06-05 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Format changes similar to CWEB.
+
+2020-05-31 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Format title page similar to CWEB.
+
+2020-05-29 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: C and CWEB refreshing for ctie.w.
+
+2020-04-30 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: More editorial modifications for ctie.w.
+
+2020-04-27 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Editorial modifications for ctie.w.
+
+2020-04-26 Andreas Scherer <https://ascherer.github.io>
+
+ * ctie-k.ch: Fix several typos in ctie.w.
+ Use British English also in the changefile.
+ Make the result TeXable, preserving section numbers.
+
+2014-06-18 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Avoid useless char subscript warnings.
+
+2014-02-12 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Handle input lines with CRLF.
+
+2013-06-28 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Include <stdio.h> after <kpathsea/kpathsea.h>.
+ Drop unused string variable 'file_open_mode'.
+
+2012-05-18 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Use binary mode for output files.
+ From Akira Kakuto <kakuto@fuk.kindai.ac.jp> (W32TeX).
+
+2010-04-10 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Replace "-[m|c]" in usage message by "-m|-c".
+
+2009-08-29 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ Avoid maximal compiler warnings.
+ * ctie-k.ch (err_print, pfatal_error, CTIEHELP, usage_help,
+ print_version_and_exit): Constify strings.
+
+2009-08-28 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ../am/cweb.am (ctie_CFLAGS): Enable compiler warnings.
+ * ctie-k.ch: Declare all functions (except main) as static.
+
+2009-08-22 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch (kpathsea_version_string): Drop nested extern decls.
+
+2009-06-23 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * ctie-k.ch: Drop P?C, P?H, use ANSI C function declarations.
+
+ * ctie-k.c (removed): obsolete, there still is ctie.c.
+
+2005-02-05 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * ctie.1: Correct header from TIE to CTIE.
+
+2005-01-21 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * ctie.1 (ctie.1): Man page correction from Eric S. Raymond
+ <esr@thyrsus.com>.
+
+2003-04-20 Julian Gilbey <jdg@debian.org>
+
+ * Remove documented need for any change files - they're not
+ actually necessary (thanks to Hartmut Henkel
+ <hartmut_henkel@gmx.de> for this observation)
+
+ * Use kpathsea 3.4.5 modified functions, losing some backward
+ compatibility if the kpathsea library is used
+
+ * Match current Web2C/Kpathsea modifications to cweb, and modify
+ to more closely match cweb 3.64 behaviour
+
+ * Release as version 1.1
+
+2002-02-03 Julian Gilbey <jdg@debian.org>
+
+ * Make success message appear on a new line at end of run
+
+ * Improve formatted output for ctie-k.ch
+
+ * Release as version 1.0
+
+2002-01-13 Julian Gilbey <jdg@debian.org>
+
+ * Initial release (version 0.9)
diff --git a/Build/source/texk/web2c/ctiedir/Makefile b/Build/source/texk/web2c/ctiedir/Makefile
new file mode 100644
index 00000000000..8edc24225cf
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/Makefile
@@ -0,0 +1,51 @@
+#
+# Makefile for ctie distribution - 21 Dec 92
+#
+# This file makes CTIE and needs ctangle from cweb distribution.
+#
+
+CTANGLE=ctangle
+BINDIR=.
+CTIE=$(BINDIR)/ctie
+
+# directory for CWEB inputs in @i files
+CWEBINPUTS= /usr/local/lib/cweb
+
+CFLAGS=
+LDFLAGS=
+KPATHSEAFLAGS=-lkpathsea
+
+default: ctie
+
+
+# CTIE
+ctie.o: ctie.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -DCWEBINPUTS=\"$(CWEBINPUTS)\" -c ctie.c
+
+ctie: ctie.o
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $(CTIE) ctie.o
+
+ctie.c: ctie.w
+ $(CTANGLE) ctie
+
+ctie-k.o: ctie-k.c
+
+ctie-k: ctie-k.o
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $(BINDIR)/ctie-k ctie-k.o $(KPATHSEAFLAGS)
+
+ctie-k.c: ctie.w ctie-k.ch
+ ctangle ctie.w ctie-k.ch ctie-k.c
+
+clean:
+ rm -f ctie.o ctie-k.o ctie.outc ctie.outm ctie.tex
+ rm -f ctie.log ctie.toc ctie.scn ctie.idx
+ rm -f ctiedoc.aux ctiedoc.log
+
+veryclean: clean
+ rm -f $(BINDIR)/ctie $(BINDIR)/ctie-k ctie.dvi ctiedoc.dvi
+
+ttest: $(CTIE)
+ $(CTIE) -c ctie.outc ctie.tie ctie.cf?
+ diff ctie.outc ctie.chf.gen
+ $(CTIE) -m ctie.outm ctie.tie ctie.cf?
+ diff ctie.outm ctie.master.gen
diff --git a/Build/source/texk/web2c/ctiedir/README b/Build/source/texk/web2c/ctiedir/README
new file mode 100644
index 00000000000..48aab880ee2
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/README
@@ -0,0 +1,75 @@
+This is the README file of the `CTIE' distribution, version 1.1
+---------------------------------------------------------------
+
+CTIE is based on the `TIE' program, a program which was first
+developed to allow WEB programmers to use more than one change file
+with their WEB programs.
+
+CWEB introduced a new command, @i, to handle "include files". The
+original TIE program was not designed to handle this situation, and so
+could not be used for all CWEB programs. CTIE behaves essentially
+identically to the original TIE, and identical results will be
+generated when TIE is applied to traditional WEB files with changes,
+as long as there are no errors. (Errors may lead to different output,
+but then the errors need correcting, anyway.)
+
+CTIE can be used to either create a new version of the (C)WEB file
+which incorporates the changes, or to merge multiple change files into
+a single change file. This program does not depend in an essential
+way on any special WEB dialect, nor on using WEB at all, as the only
+controls to be interpreted are the change requests in the change files
+(delimited by @x, @y and @z) and file include commands (indicated by @i).
+This makes `CTIE' also usable for any other language, or even
+data files. See the documentation ctiedoc.tex and the example file
+ctie.tie for more information.
+
+
+REQUIREMENTS:
+
+This version of `CTIE' is written in CWEB. To preprocess and compile
+the source you will need a working `ctangle'. A pretangled ctie.c is
+supplied if you do not have a working ctangle available.
+
+Please note, that the CWEB by Silvio Levy and Donald E. Knuth must
+probably be at least at version 2.8, to process and compile `ctie'
+without problems.
+
+Furthermore, a ctie-k.ch file is provided which links ctie against
+Karl Berry's kpathsea library. A tangled version of this file is
+provided as ctie-k.c. To use this, you will need to link against
+version 3.4.5 or higher of the kpathsea library. This version
+searches for files, both from the command line and included (@i) files
+using the CWEBINPUTS search path.
+
+
+DISTRIBUTION:
+
+This package has been uploaded to CTAN, and appears in the directory
+web/c_cpp/ctie/.
+
+
+LICENCE:
+
+This program is based on tie.w and common.w (part of CWEB). It is
+distributed with the following licence.
+
+Copyright (c) 2002,2003 by Julian Gilbey
+All rights reserved.
+
+This program is distributed WITHOUT ANY WARRANTY, express or implied.
+
+Permission is granted to make and distribute verbatim copies of this
+program 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
+program 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.
+
+
+BUGS/ENHANCEMENTS:
+
+If you detect bugs in the implementation of CTIE or have suggestions
+to enhance functionality or improve portability, please send a message
+to Julian Gilbey <jdg@debian.org>.
diff --git a/Build/source/texk/web2c/ctiedir/ctie-k.ch b/Build/source/texk/web2c/ctiedir/ctie-k.ch
new file mode 100644
index 00000000000..ccd8f157b59
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie-k.ch
@@ -0,0 +1,727 @@
+% Changes to adapt CTIE to web2c.
+% Copyright 2002,2003 Julian Gilbey
+% All rights reserved.
+%
+% This file is distributed WITHOUT ANY WARRANTY, express or implied.
+%
+% Permission is granted to make and distribute verbatim copies of this
+% file 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
+% file 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.
+%
+% This file is based heavily on tie.ch by Olaf Weber to adapt tie.w to
+% the web2c system and on comm-w2c.ch from the Web2C 7.4.5 distribution
+% by Wlodek Bzyl and Olaf Weber.
+
+@x l.19 Add macro definitions
+\def\title{The CTIE processor}
+\def\botofcontents{%
+\vfill
+$\copyright$ 2002,2003 Julian Gilbey
+
+All rights reserved.
+
+This program is distributed WITHOUT ANY WARRANTY, express or implied.
+
+Permission is granted to make and distribute verbatim copies of this
+program 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
+program 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.
+}
+@y
+\def\Kpathsea/{{\mc KPATHSEA\spacefactor1000}}
+\let\maybe=\iftrue
+\def\title{The CTIE processor}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont CTIE} processor}
+ \vskip 15pt
+ \centerline{(Version 1.1 [\TeX~Live])}
+ \vfill}
+\def\covernote{\vbox{\ninerm\noindent
+Copyright \copyright\ 2002, 2003 Julian Gilbey
+\smallskip\noindent
+All rights reserved.
+\bigskip\noindent
+This program is distributed WITHOUT ANY WARRANTY, express or implied.
+\smallskip\noindent
+Permission is granted to make and distribute verbatim copies of this
+program 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
+program 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.
+}}
+\datecontentspage
+@z
+
+@x l.81
+@d copyright
+ "Copyright 2002,2003 Julian Gilbey. All rights reserved. There is no warranty.\n\
+Run with the --version option for other important information."
+@y
+@d copyright
+ "Copyright 2002,2003 Julian Gilbey."@|
+ " All rights reserved. There is no warranty.\n"@|
+ "Run with the --version option for other important information."
+@z
+
+@x l.102
+main(argc, argv)
+ int argc; string *argv;
+@y
+int main (int argc, string *argv)
+@z
+
+@x l.105 Set up kpathsea stuff
+ @<Initialise parameters@>;
+@y
+ @<Set up |PROGNAME| feature and initialise the search path mechanism@>@;
+ @<Initialise parameters@>@;
+@z
+
+@x l.107
+ @<Print the banners@>;
+@y
+ @<Print the banners@>@;
+@z
+
+boolean and string are defined by kpathsea.
+@x l.116
+@ We include the additional types |boolean| and |string|. \.{CTIE}
+replaces the complex \.{TIE} character set handling (based on that of
+the original \.{WEB} system) with the standard \.{CWEB} behaviour, and
+so uses the |char| type for input and output.
+
+@d false 0
+@d true 1
+
+@<Global types@>=
+typedef int boolean;
+typedef char* string;
+@y
+@ We include the additional types |boolean| and |string|. \.{CTIE}
+replaces the complex \.{TIE} character set handling (based on that of
+the original \.{WEB} system) with the standard \.{CWEB} behaviour, and
+so uses the |char| type for input and output.
+
+The \.{kpathsea} library (version 3.4.5 and higher) defines the |@!boolean|
+(with the values |@!true| and |@!false|) and |@!string| (and |@!const_string|)
+types in \.{<kpathsea/simpletypes.h>}, so we do not actually need to define
+them here.
+
+@s boolean int
+@s string int
+@s const_string int
+@z
+
+@x l.129 The kpathsea include files find the right header file for these.
+@ We predeclare some standard string-handling 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. (There's confusion
+between \.{<string.h>} and \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+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 */
+extern char *strerror();
+@y
+@ We don't need to predeclare any string handling functions here, as
+the \.{kpathsea} headers do the right thing by including \.{<string.h>}
+behind the scenes.
+@z
+
+@x l.149
+@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
+@y
+@d xisupper(c) (isupper((unsigned char)c)&&((unsigned char)c<0200))
+@z
+
+@x l.155
+This variable must be initialized.
+@y
+This variable must be initialised.
+@z
+
+@x l.158
+@d spotless 0
+@d troublesome 1
+@d fatal 2
+
+@<Global variables@>=
+int history=spotless;
+@y
+@<Global variables@>=
+typedef enum {
+ @!spotless,
+ @!troublesome,
+ @!fatal } return_code;
+static return_code history=spotless;
+@z
+
+@x l.170 The kpathsea include files must be first.
+predefined as we include the \.{stdio.h} definitions.
+
+@<Global \&{\#include}s@>=
+#include <stdio.h>
+@y
+predefined as we include the \.{<stdio.h>} definitions
+through the \.{kpathsea} interface.
+
+@<Global \&{\#include}s@>=
+#include <kpathsea/kpathsea.h>
+@z
+
+@x l.176 And this.
+@ And we need dynamic memory allocation.
+This should cause no trouble in any \CEE/ program.
+@^system dependencies@>
+
+@<Global \&{\#include}s@>=
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+@y
+@ And we need dynamic memory allocation.
+This should cause no trouble in any \CEE/ program.
+The \.{kpathsea} include files handle the definition of |@!malloc|, too.
+@^system dependencies@>
+@z
+
+@x l.190
+files) are treated the same way. To organize the
+@y
+files) are treated the same way. To organise the
+@z
+
+Sections 10 and 11: use enum as requested in ctie.w
+
+@x l.204
+\leavevmode |file_types| is used to describe whether a file
+@y
+\leavevmode \&{file\_types} is used to describe whether a file
+@z
+
+@x l.208
+the kind of output. (this would even be necessary if we
+@y
+the kind of output. (This would even be necessary if we
+@z
+
+@x l.212
+#define search 0
+#define test 1
+#define reading 2
+#define ignore 3
+typedef int in_file_modes; /* should be |enum(search, test, reading, ignore)| */
+#define unknown 0
+#define master 1
+#define chf 2
+typedef int file_types; /* should be |enum(unknown, master, chf)| */
+@y
+typedef enum {
+ @!search,
+ @!test,
+ @!reading,
+ @!ignore } in_file_modes;
+typedef enum {
+ @!unknown,
+ @!master,
+ @!chf } file_types;
+@z
+
+@x l.223
+@ A variable of type |out_md_type| will tell us in what state the output
+@y
+@ A variable of type \&{out\_md\_type} will tell us in what state the output
+@z
+
+@x l.230 dito
+#define normal 0
+#define pre 1
+#define post 2
+typedef int out_md_type; /* should be |enum(normal, pre, post)| */
+@y
+typedef enum {
+ @!normal,
+ @!pre,
+ @!post } out_md_type;
+@z
+
+@x l.284 way too short!
+@d max_file_name_length 60
+@y
+@d max_file_name_length 1024
+@z
+
+@x l.329
+boolean get_line(i, do_includes)
+ file_index i; boolean do_includes;
+@y
+static boolean
+get_line (file_index i, boolean do_includes)
+@z
+
+@x l.361
+replacement part of a change file, or in an incomplerte check if the
+@y
+replacement part of a change file, or in an incomplete check if the
+@z
+
+Handle input lines with CRLF
+
+@x l.376
+ if ((*(k++) = c) != ' ') inp_desc->limit = k;
+@y
+ if ((*(k++) = c) != ' ' && c != '\r') inp_desc->limit = k;
+@z
+
+@x l.386
+ @<Increment the line number and print a progess report at
+@y
+ @<Increment the line number and print a progress report at
+@z
+
+@x l.436
+ if ((*(k++) = c) != ' ') inp_desc->limit = k;
+@y
+ if ((*(k++) = c) != ' ' && c != '\r') inp_desc->limit = k;
+@z
+
+The next piece is simplified using the kpathsea kpse_find_file
+function.
+
+@x l.497
+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.)
+@y
+We use the \Kpathsea/ library (in particular, the \.{CWEBINPUTS}
+variable) to search for this file.@.CWEBINPUTS@>
+@z
+
+@x l.510 Don't need the same variables any longer
+ char temp_file_name[max_file_name_length];
+ char *file_name_end;
+ char *k, *kk;
+ int l; /* length of file name */
+@y
+ char *file_name_end;
+ string fullname;
+ char *k;
+@z
+
+@x l.534 Replace with kpse_find_file
+ if ((new_inc->the_file=fopen(new_inc->file_name, "r"))!=NULL) {
+@y
+ fullname=kpse_find_cweb(new_inc->file_name);
+ if (fullname)
+ new_inc->the_file=fopen(fullname, "r");
+ if (fullname!=NULL && new_inc->the_file!=NULL) {
+ free(fullname);
+@z
+
+@x l.539 And this part is replaced by kpse_find_file
+ 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>=file_name_end) too_long();
+ for (; k>= new_inc->file_name; k--) *(k+l+1)=*k;
+ strcpy(new_inc->file_name, temp_file_name);
+ new_inc->file_name[l]='/'; /* \UNIX/ pathname separator */
+ if ((new_inc->the_file=fopen(new_inc->file_name, "r"))!=NULL) {
+ new_inc->parent=inp_desc->current_include; /* link it in */
+ inp_desc->current_include=new_inc;
+ goto restart; /* success */
+ }
+ }
+@y
+@z
+
+@x l.565 slightly more useful error message
+ err_print(i, "! Cannot open include file");
+@y
+ if (fullname) {
+ free(fullname);
+ err_print(i, "! Cannot open include file");
+ } else
+ err_print(i, "! Cannot find include file");
+@z
+
+
+@x l.585
+void err_print();
+@y
+void err_print (file_index, const char *);
+@z
+
+@x l.590
+void err_print(i, s) /* prints `\..' and location of error message */
+file_index i; char *s;
+@y
+void err_print (file_index i, const char *s)
+/* prints `\..' and location of error message */
+@z
+
+@x l.664
+int wrap_up()
+@y
+int wrap_up (void)
+@z
+
+@x l.667
+ if (history > spotless) return 1;
+ else return 0;
+@y
+ if (history > spotless) return EXIT_FAILURE;
+ else return EXIT_SUCCESS;
+@z
+
+@x l.674
+int wrap_up();
+@y
+int wrap_up (void);
+@z
+
+@x l.697
+void pfatal_error();
+@y
+void pfatal_error (const char *, const char *);
+@z
+
+@x l.700
+void pfatal_error(s, t)
+char *s, *t;
+@y
+void pfatal_error (const char *s, const char *t)
+@z
+
+@x l.713
+@ We need an include file for the above.
+
+@<Global \&{\#include}s@>=
+#include <errno.h>
+@y
+@ The \.{<errno.h>} include file for the above comes via the \.{kpathsea}
+interface.
+@z
+
+@x l.731 Use binary mode for output files
+ out_file=fopen(out_name, "w");
+@y
+ out_file=fopen(out_name, "wb");
+@z
+
+@x l.739
+@ The name of the file and the file desciptor are stored in
+@y
+@ The name of the file and the file descriptor are stored in
+@z
+
+@x l.747 Use the kpathsea library to do this
+@ For the master file we start by reading its first line into the
+buffer, if we could open it.
+
+@<Get the master file started@>=
+{
+ input_organisation[0]->the_file=
+ fopen(input_organisation[0]->file_name, "r");
+
+ if (input_organisation[0]->the_file==NULL)
+ pfatal_error("! Cannot open master file ",
+ input_organisation[0]->file_name);
+@.Cannot open master file@>
+@y
+@ For the master file we start by reading its first line into the
+buffer, if we could open it. We use the \.{kpathsea} library to find
+the file.
+
+@<Get the master file started@>=
+{
+ string fullname;
+
+ fullname = kpse_find_cweb(input_organisation[0]->file_name);
+ if (fullname)
+ input_organisation[0]->the_file = fopen(fullname, "r");
+
+ if (fullname==NULL || input_organisation[0]->the_file==NULL) {
+ if (fullname) {
+ pfatal_error("! Cannot open master file ",
+ input_organisation[0]->file_name);
+ } else {
+ fatal_error(-1, "! Cannot find master file ",
+ input_organisation[0]->file_name);
+ }
+ }
+ else free(fullname);
+@.Cannot open master file@>
+@.Cannot find master file@>
+@z
+
+@x l.768 And this
+@<Prepare the change files@>=
+{
+ file_index i;
+
+ i=1;
+ while (i<no_ch) {
+ input_organisation[i]->the_file=
+ fopen(input_organisation[i]->file_name, "r");
+ if (input_organisation[i]->the_file==NULL)
+ pfatal_error("! Cannot open change file ",
+ input_organisation[i]->file_name);
+@.Cannot open change file@>
+@y
+@<Prepare the change files@>=
+{
+ file_index i;
+ string fullname;
+
+ i=1;
+ while (i<no_ch) {
+ fullname = kpse_find_cweb(input_organisation[i]->file_name);
+ if (fullname)
+ input_organisation[i]->the_file = fopen(fullname, "r");
+
+ if (fullname==NULL || input_organisation[i]->the_file==NULL) {
+ if (fullname) {
+ pfatal_error("! Cannot open change file ",
+ input_organisation[i]->file_name);
+ } else {
+ fatal_error(-1, "! Cannot find change file ",
+ input_organisation[i]->file_name);
+ }
+ }
+ else free(fullname);
+@.Cannot open change file@>
+@.Cannot find change file@>
+@z
+
+@x l.792
+boolean lines_dont_match(i, j)
+ file_index i, j;
+@y
+static boolean
+lines_dont_match (file_index i, file_index j)
+@z
+
+@x l.809
+void init_change_file(i)
+ file_index i;
+@y
+static void
+init_change_file (file_index i)
+@z
+
+@x l.833
+ if (xisupper(ccode)) ccode=tolower(ccode);
+@y
+ if (xisupper(ccode)) ccode=tolower((unsigned char)ccode);
+@z
+
+@x l.858
+void put_line(j)
+ file_index j;
+@y
+static void
+put_line (file_index j)
+@z
+
+@x l.873
+boolean e_of_ch_module(i)
+ file_index i;
+@y
+static boolean
+e_of_ch_module (file_index i)
+@z
+
+@x l.894
+boolean e_of_ch_preamble(i)
+ file_index i;
+@y
+static boolean
+e_of_ch_preamble (file_index i)
+@z
+
+@x l.1106
+void usage_error()
+{
+ @<Print the banners@>;
+ fprintf(stderr, "Usage: ctie -[mc] outfile master changefile(s)\n");
+@y
+static void
+usage_error (void)
+{
+ @<Print the banners@>;
+ fprintf(stderr, "Usage: ctie -m|-c outfile master changefile(s)\n");
+@z
+
+@x l.1111
+ exit(1);
+@y
+ exit(EXIT_FAILURE);
+@z
+
+@x l.1119 Add Web2C version to banner string
+printf("%s\n", banner); /* print a ``banner line'' */
+@y
+printf("%s (%s)\n", banner, kpathsea_version_string); /* print a ``banner line'' */
+@z
+
+Section 63: use 'none' more than once.
+
+@x l.1169
+(which is the case if |no_ch==(-1)|) or if the next element of
+@y
+(which is the case if |no_ch==none|) or if the next element of
+@z
+
+@x l.1174
+ if (no_ch==(-1)) {
+@y
+ if (no_ch==none) {
+@z
+
+@x l.1218
+string CTIEHELP[] = {
+ "Usage: ctie -[mc] outfile master changefile(s)",
+@y
+const_string CTIEHELP[] = {
+ "Usage: ctie -m|-c outfile master changefile(s)",
+@z
+
+@x l.1233
+void usage_help();
+void print_version_and_exit();
+@y
+static void usage_help (void);
+static void print_version_and_exit (const_string, const_string);
+@z
+
+@x l.1238
+void usage_help()
+{
+ string *message=CTIEHELP;
+@y
+static void
+usage_help (void)
+{
+ const_string *message=CTIEHELP;
+@z
+
+@x l.1248
+ exit(0);
+@y
+ exit(EXIT_SUCCESS);
+@z
+
+@x l.1253
+void print_version_and_exit(name, version)
+ string name, version;
+{
+ printf ("%s %s\n", name, version);
+
+ puts ("Copyright (C) 2002,2003 Julian Gilbey.");
+
+ puts ("There is NO warranty. This is free software. See the source");
+ puts ("code of CTIE for redistribution conditions.");
+
+ exit (0);
+}
+@y
+static void
+print_version_and_exit (const_string name, const_string version)
+{
+ printf ("%s %s\n", name, version);
+ puts (kpathsea_version_string);
+
+ puts ("Copyright (C) 2002,2003 Julian Gilbey.");
+ puts ("Kpathsea is copyright (C) 1999 Free Software Foundation, Inc.");
+
+ puts ("There is NO warranty. This is free software.");
+ puts ("Redistribution of this software is covered by the terms of");
+ puts ("both the CTIE copyright and the GNU General Public Licence.");
+ puts ("For more information about these matters, see the files");
+ puts ("named COPYING and the CTIE source.");
+ puts ("Primary author of CTIE: Julian Gilbey.");
+ puts ("Kpathsea written by Karl Berry and others.");
+
+ exit (EXIT_SUCCESS);
+}
+@z
+
+We use the path-searching initialisation code
+taken almost verbatim from comm-w2c.ch.
+
+@x l.1267
+@* System-dependent changes.
+This section should be replaced, if necessary, by
+changes to the program that are necessary to make \.{CTIE}
+work at a particular installation. It is usually best to
+design your change file so that all changes to previous
+modules preserve the module numbering; then everybody's
+version will be consistent with the printed program. More
+extensive changes, which introduce new modules, can be
+inserted here; then only the index itself will get a new
+module number.
+@^system dependencies@>
+@y
+@* System-dependent changes.@^system dependencies@>@.CWEBINPUTS@>
+The \.{ctie} program from the original \.{CTIE} package uses 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:
+\smallskip
+{\parindent5em
+\item{(a)} a user-set environment variable \.{CWEBINPUTS}
+ (overridden by \.{CWEBINPUTS\_ctie});
+\item{(b)} a line in \Kpathsea/ configuration file \.{texmf.cnf},\hfil\break
+ e.g., \.{CWEBINPUTS=\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//}\hfil\break
+ or \.{CWEBINPUTS.ctie=\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//};
+\item{(c)} compile-time default directories (specified in
+ \.{texmf.in}),\hfil\break
+ i.e., \.{\$TEXMFDOTDIR:\$TEXMF/texmf/cweb//}.\par}
+
+@d kpse_find_cweb(name) kpse_find_file(name, kpse_cweb_format, true)
+
+@ The simple file searching is replaced by the `path searching'
+mechanism that the \Kpathsea/ library provides.
+
+We set |kpse_program_name| to `\.{ctie}'. This means if the variable
+\.{CWEBINPUTS.ctie} is present in \.{texmf.cnf} (or \.{CWEBINPUTS\_ctie}
+in the environment) its value will be used as the search path for
+filenames. This allows different flavors of \.{CTIE} to have
+different search paths.@.CWEBINPUTS@>
+
+@<Set up |PROGNAME| feature...@>=
+kpse_set_program_name(argv[0], "ctie");
+@z
diff --git a/Build/source/texk/web2c/ctiedir/ctie.1 b/Build/source/texk/web2c/ctiedir/ctie.1
new file mode 100644
index 00000000000..8058d364e5a
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.1
@@ -0,0 +1,55 @@
+.TH CTIE 1 20/04/2003
+.SH NAME
+ctie \- merge or apply CWEB change files
+.SH SYNOPSIS
+.B ctie
+.B \-c|\-m
+.I outputfile masterfile changefile...
+
+.SH DESCRIPTION
+The
+.I CTIE
+program is used to process multiple change files used with the CWEB
+system for literate programming. The CWEB programs allow one to apply
+patches to a source file (the
+.IR masterfile )
+by means of a single change file.
+.I CTIE
+can be used to either merge up to 32 change files into a single one or
+to apply the changes to the
+.I masterfile
+in order to create a new master file. Output of either the new change
+file or the patched master file goes into
+.IR outputfile .
+Any include files (indicated using the CWEB
+.I @i
+command) are fully expanded during
+.I CTIE
+processing, which means that the change files are able to modify the
+contents of any included files. Also, if this program has been
+compiled using the
+.I kpathsea
+library, then files are searched for using the
+.I CWEBINPUTS
+environment variable, as described in the
+.I kpathsea
+documentation.
+.SH OPTIONS
+.TP
+.B \-c
+Create a single change file from the given
+.IR changefiles .
+.TP
+.B \-m
+Create a new master file by applying the given
+.IR changefiles .
+.SH "SEE ALSO"
+.BR cweb (1),
+.IR ctiedoc.tex ,
+.BR tie (1),
+.BR web (1).
+.SH "AUTHOR"
+Julian Gilbey, jdg@debian.org. The original TIE program was by Klaus
+Guntermann, TH Darmstadt, Institut f. Theoretische Informatik. The
+TIE man page was by Joachim Schnitter, TH Darmstadt, Phys. Chemie I,
+and was modified for CTIE by Julian Gilbey.
diff --git a/Build/source/texk/web2c/ctiedir/ctie.c b/Build/source/texk/web2c/ctiedir/ctie.c
new file mode 100644
index 00000000000..840c7800144
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.c
@@ -0,0 +1,1111 @@
+#define version_number "1.1"
+#define banner "This is CTIE, Version 1.1"
+#define copyright \
+"Copyright 2002,2003 Julian Gilbey. All rights reserved. There is no warranty.\n\
+Run with the --version option for other important information." \
+ \
+
+#define false 0
+#define true 1 \
+
+#define buf_size 1024
+#define max_file_index 32 \
+
+#define xisupper(c) (isupper(c) &&((unsigned char) c<0200) ) \
+ \
+
+#define spotless 0
+#define troublesome 1
+#define fatal 2 \
+
+#define max_include_files 20 \
+
+#define max_file_name_length 60 \
+
+#define too_long() {total_include_files--;free(new_inc) ; \
+err_print(i,"! Include file name too long") ;goto restart;} \
+
+#define fatal_error(i,s,t) { \
+fprintf(stderr,"\n%s",s) ; \
+err_print(i,t) ; \
+history= fatal; \
+exit(wrap_up() ) ; \
+} \
+ \
+
+#define none (-1) \
+
+/*2:*/
+#line 89 "./ctie.w"
+
+/*8:*/
+#line 172 "./ctie.w"
+
+#include <stdio.h>
+
+
+/*:8*//*9:*/
+#line 180 "./ctie.w"
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+
+/*:9*//*37:*/
+#line 715 "./ctie.w"
+
+#include <errno.h>
+
+
+/*:37*/
+#line 90 "./ctie.w"
+
+/*4:*/
+#line 124 "./ctie.w"
+
+typedef int boolean;
+typedef char*string;
+
+
+/*:4*//*10:*/
+#line 211 "./ctie.w"
+
+#define search 0
+#define test 1
+#define reading 2
+#define ignore 3
+typedef int in_file_modes;
+#define unknown 0
+#define master 1
+#define chf 2
+typedef int file_types;
+
+
+/*:10*//*11:*/
+#line 229 "./ctie.w"
+
+#define normal 0
+#define pre 1
+#define post 2
+typedef int out_md_type;
+
+
+/*:11*//*12:*/
+#line 239 "./ctie.w"
+
+typedef int file_index;
+
+
+/*:12*//*13:*/
+#line 246 "./ctie.w"
+
+typedef struct _indsc{
+char file_name[max_file_name_length];
+long line;
+FILE*the_file;
+struct _indsc*parent;
+}include_description;
+
+
+/*:13*//*14:*/
+#line 259 "./ctie.w"
+
+typedef struct _idsc{
+string file_name;
+char buffer[buf_size];
+in_file_modes mode;
+long line;
+file_types type_of_file;
+include_description*current_include;
+char*buffer_end;
+char*limit;
+char*loc;
+FILE*the_file;
+int dont_match;
+}input_description;
+
+
+/*:14*/
+#line 91 "./ctie.w"
+
+/*5:*/
+#line 134 "./ctie.w"
+
+extern int strlen();
+extern char*strcpy();
+extern int strncmp();
+extern char*strncpy();
+extern char*strerror();
+
+
+/*:5*//*28:*/
+#line 584 "./ctie.w"
+
+void err_print();
+
+/*:28*//*33:*/
+#line 673 "./ctie.w"
+
+int wrap_up();
+
+/*:33*//*35:*/
+#line 696 "./ctie.w"
+
+void pfatal_error();
+
+/*:35*//*67:*/
+#line 1232 "./ctie.w"
+
+void usage_help();
+void print_version_and_exit();
+
+
+/*:67*/
+#line 92 "./ctie.w"
+
+/*7:*/
+#line 162 "./ctie.w"
+
+int history= spotless;
+
+
+/*:7*//*15:*/
+#line 286 "./ctie.w"
+
+int total_include_files= 0;
+
+/*:15*//*16:*/
+#line 292 "./ctie.w"
+
+file_index actual_input,test_input,no_ch;
+file_types prod_chf= unknown;
+out_md_type out_mode;
+
+/*:16*//*18:*/
+#line 309 "./ctie.w"
+
+input_description*input_organisation[max_file_index+1];
+
+
+/*:18*//*22:*/
+#line 406 "./ctie.w"
+
+boolean input_has_ended= false;
+
+
+/*:22*//*39:*/
+#line 742 "./ctie.w"
+
+FILE*out_file;
+string out_name;
+
+
+/*:39*//*66:*/
+#line 1217 "./ctie.w"
+
+string CTIEHELP[]= {
+"Usage: ctie -[mc] outfile master changefile(s)",
+" Create a new master file or change file from the given",
+" master (C)WEB file and changefiles.",
+" All filenames are taken literally; no suffixes are added.",
+"",
+"-m create a new master file from original (C)WEB and change file(s)",
+"-c create a master change file for original (C)WEB file from changefile(s)",
+"--help display this help and exit",
+"--version display version information and exit",
+NULL
+};
+
+
+/*:66*/
+#line 93 "./ctie.w"
+
+/*29:*/
+#line 589 "./ctie.w"
+
+void err_print(i,s)
+file_index i;char*s;
+{
+char*k,*l;
+fprintf(stderr,*s=='!'?"\n%s":"%s",s);
+if(i>=0)/*30:*/
+#line 611 "./ctie.w"
+
+{
+register input_description*inp_desc= input_organisation[i];
+register include_description*inc_desc= inp_desc->current_include;
+
+if(inc_desc!=NULL){
+fprintf(stderr,". (l. %ld of include file %s",inc_desc->line,
+inc_desc->file_name);
+fprintf(stderr," included from l. %ld of %s file %s)\n",
+inp_desc->line,
+inp_desc->type_of_file==master?"master":"change",
+inp_desc->file_name);
+}
+else
+fprintf(stderr,". (l. %ld of %s file %s)\n",inp_desc->line,
+inp_desc->type_of_file==master?"master":"change",
+inp_desc->file_name);
+l= (inp_desc->loc>=inp_desc->limit?inp_desc->limit:inp_desc->loc);
+if(l> inp_desc->buffer){
+for(k= inp_desc->buffer;k<l;k++)
+if(*k=='\t')putc(' ',stderr);
+else putc(*k,stderr);
+putc('\n',stderr);
+for(k= inp_desc->buffer;k<l;k++)
+putc(' ',stderr);
+}
+for(k= l;k<inp_desc->limit;k++)
+putc(*k,stderr);
+putc('\n',stderr);
+}
+
+
+/*:30*/
+#line 595 "./ctie.w"
+
+else putc('\n',stderr);
+fflush(stderr);
+history= troublesome;
+}
+
+/*:29*//*36:*/
+#line 699 "./ctie.w"
+
+void pfatal_error(s,t)
+char*s,*t;
+{
+char*strerr= strerror(errno);
+
+fprintf(stderr,"\n%s%s",s,t);
+if(strerr)fprintf(stderr," (%s)\n",strerr);
+else fprintf(stderr,"\n");
+history= fatal;
+exit(wrap_up());
+}
+
+
+/*:36*/
+#line 94 "./ctie.w"
+
+/*19:*/
+#line 328 "./ctie.w"
+
+boolean get_line(i,do_includes)
+file_index i;boolean do_includes;
+{
+register input_description*inp_desc= input_organisation[i];
+register FILE*fp;
+
+if(inp_desc->mode==ignore)return false;
+
+restart:
+if(inp_desc->current_include!=NULL){
+register include_description*inc_desc= inp_desc->current_include;
+
+fp= inc_desc->the_file;
+/*24:*/
+#line 426 "./ctie.w"
+
+{
+register int c;
+register char*k;
+
+if(feof(fp))
+/*25:*/
+#line 452 "./ctie.w"
+
+{
+include_description*temp= inc_desc->parent;
+
+fclose(fp);
+free(inc_desc);
+total_include_files--;
+inp_desc->current_include= temp;
+goto restart;
+}
+
+
+/*:25*/
+#line 432 "./ctie.w"
+
+
+inp_desc->limit= k= inp_desc->buffer;
+while(k<=inp_desc->buffer_end&&(c= getc(fp))!=EOF&&c!='\n')
+if((*(k++)= c)!=' ')inp_desc->limit= k;
+if(k> inp_desc->buffer_end)
+if((c= getc(fp))!=EOF&&c!='\n'){
+ungetc(c,fp);inp_desc->loc= inp_desc->buffer;
+err_print(i,"! Input line too long");
+
+}
+if(c==EOF&&inp_desc->limit==inp_desc->buffer)
+/*25:*/
+#line 452 "./ctie.w"
+
+{
+include_description*temp= inc_desc->parent;
+
+fclose(fp);
+free(inc_desc);
+total_include_files--;
+inp_desc->current_include= temp;
+goto restart;
+}
+
+
+/*:25*/
+#line 444 "./ctie.w"
+
+
+inc_desc->line++;
+}
+
+/*:24*/
+#line 342 "./ctie.w"
+
+}
+else{
+fp= inp_desc->the_file;
+/*20:*/
+#line 366 "./ctie.w"
+
+{
+register int c;
+register char*k;
+
+if(feof(fp))
+/*21:*/
+#line 394 "./ctie.w"
+
+{
+inp_desc->mode= ignore;
+inp_desc->limit= NULL;
+if(inp_desc->type_of_file==master)input_has_ended= true;
+fclose(fp);
+return false;
+}
+
+
+/*:21*/
+#line 372 "./ctie.w"
+
+
+inp_desc->limit= k= inp_desc->buffer;
+while(k<=inp_desc->buffer_end&&(c= getc(fp))!=EOF&&c!='\n')
+if((*(k++)= c)!=' ')inp_desc->limit= k;
+if(k> inp_desc->buffer_end)
+if((c= getc(fp))!=EOF&&c!='\n'){
+ungetc(c,fp);inp_desc->loc= inp_desc->buffer;
+err_print(i,"! Input line too long");
+
+}
+if(c==EOF&&inp_desc->limit==inp_desc->buffer)
+/*21:*/
+#line 394 "./ctie.w"
+
+{
+inp_desc->mode= ignore;
+inp_desc->limit= NULL;
+if(inp_desc->type_of_file==master)input_has_ended= true;
+fclose(fp);
+return false;
+}
+
+
+/*:21*/
+#line 384 "./ctie.w"
+
+
+/*23:*/
+#line 414 "./ctie.w"
+
+inp_desc->line++;
+if(inp_desc->type_of_file==master&&inp_desc->line%100==0){
+if(inp_desc->line%500==0)printf("%ld",inp_desc->line);
+else putchar('.');
+fflush(stdout);
+}
+
+
+/*:23*/
+#line 387 "./ctie.w"
+
+}
+
+
+/*:20*/
+#line 346 "./ctie.w"
+
+}
+
+if(do_includes)
+/*26:*/
+#line 467 "./ctie.w"
+
+{
+inp_desc->loc= inp_desc->buffer;
+*inp_desc->limit= ' ';
+if(*inp_desc->buffer=='@'&&
+(inp_desc->buffer[1]=='i'||inp_desc->buffer[1]=='I')){
+inp_desc->loc= inp_desc->buffer+2;
+*inp_desc->limit= '"';
+while(*inp_desc->loc==' '||*inp_desc->loc=='\t')
+inp_desc->loc++;
+if(inp_desc->loc>=inp_desc->limit){
+err_print(i,"! Include file name not given");
+
+goto restart;
+}
+if(total_include_files>=max_include_files){
+err_print(i,"! Too many nested includes");
+
+goto restart;
+}
+total_include_files++;
+/*27:*/
+#line 507 "./ctie.w"
+
+{
+include_description*new_inc;
+char temp_file_name[max_file_name_length];
+char*file_name_end;
+char*k,*kk;
+int l;
+
+new_inc= (include_description*)malloc(sizeof(include_description));
+if(new_inc==NULL)
+fatal_error(i,"! No memory for new include descriptor","");
+new_inc->line= 0;
+k= new_inc->file_name;
+file_name_end= k+max_file_name_length-1;
+
+if(*inp_desc->loc=='"'){
+inp_desc->loc++;
+while(*inp_desc->loc!='"'&&k<=file_name_end)
+*k++= *inp_desc->loc++;
+if(inp_desc->loc==inp_desc->limit)
+k= file_name_end+1;
+}else
+while(*inp_desc->loc!=' '&&*inp_desc->loc!='\t'&&
+*inp_desc->loc!='"'&&k<=file_name_end)*k++= *inp_desc->loc++;
+if(k> file_name_end)too_long();
+
+*k= '\0';
+if((new_inc->the_file= fopen(new_inc->file_name,"r"))!=NULL){
+new_inc->parent= inp_desc->current_include;
+inp_desc->current_include= new_inc;
+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>=file_name_end)too_long();
+for(;k>=new_inc->file_name;k--)*(k+l+1)= *k;
+strcpy(new_inc->file_name,temp_file_name);
+new_inc->file_name[l]= '/';
+if((new_inc->the_file= fopen(new_inc->file_name,"r"))!=NULL){
+new_inc->parent= inp_desc->current_include;
+inp_desc->current_include= new_inc;
+goto restart;
+}
+}
+total_include_files--;
+free(new_inc);
+err_print(i,"! Cannot open include file");
+
+goto restart;
+}
+
+
+
+/*:27*/
+#line 488 "./ctie.w"
+;
+}
+}
+
+
+/*:26*/
+#line 351 "./ctie.w"
+
+return true;
+}
+
+
+/*:19*//*32:*/
+#line 663 "./ctie.w"
+
+int wrap_up()
+{
+/*34:*/
+#line 682 "./ctie.w"
+
+switch(history){
+case spotless:
+printf("\n(No errors were found.)\n");break;
+case troublesome:
+printf("\n(Pardon me, but I think I spotted something wrong.)\n");break;
+case fatal:printf("(That was a fatal error, my friend.)\n");
+}
+
+
+/*:34*/
+#line 666 "./ctie.w"
+;
+if(history> spotless)return 1;
+else return 0;
+}
+
+/*:32*//*42:*/
+#line 791 "./ctie.w"
+
+boolean lines_dont_match(i,j)
+file_index i,j;
+{
+register input_description*iptr= input_organisation[i],
+*jptr= input_organisation[j];
+
+if(iptr->limit-iptr->buffer!=jptr->limit-jptr->buffer)
+return true;
+return strncmp(iptr->buffer,jptr->buffer,iptr->limit-iptr->buffer);
+}
+
+
+/*:42*//*43:*/
+#line 808 "./ctie.w"
+
+void init_change_file(i)
+file_index i;
+{
+register input_description*inp_desc= input_organisation[i];
+char ccode;
+
+inp_desc->limit= inp_desc->buffer;
+/*44:*/
+#line 827 "./ctie.w"
+
+while(1){
+if(!get_line(i,false))return;
+if(inp_desc->limit<inp_desc->buffer+2)continue;
+if(inp_desc->buffer[0]!='@')continue;
+ccode= inp_desc->buffer[1];
+if(xisupper(ccode))ccode= tolower(ccode);
+if(ccode=='x')break;
+if(ccode=='y'||ccode=='z'||ccode=='i'){
+inp_desc->loc= inp_desc->buffer+2;
+err_print(i,"! Missing @x in change file");
+
+}
+}
+
+/*:44*/
+#line 816 "./ctie.w"
+
+/*45:*/
+#line 844 "./ctie.w"
+
+do{
+if(!get_line(i,true)){
+err_print(i,"! Change file ended after @x");
+
+return;
+}
+}while(inp_desc->limit==inp_desc->buffer);
+
+
+/*:45*/
+#line 817 "./ctie.w"
+
+inp_desc->dont_match= 0;
+}
+
+
+/*:43*//*46:*/
+#line 857 "./ctie.w"
+
+void put_line(j)
+file_index j;
+{
+char*ptr= input_organisation[j]->buffer;
+char*lmt= input_organisation[j]->limit;
+
+while(ptr<lmt)putc(*ptr++,out_file);
+putc('\n',out_file);
+}
+
+
+/*:46*//*47:*/
+#line 872 "./ctie.w"
+
+boolean e_of_ch_module(i)
+file_index i;
+{
+register input_description*inp_desc= input_organisation[i];
+
+if(inp_desc->limit==NULL){
+err_print(i,"! Change file ended without @z");
+
+return true;
+}else if(inp_desc->limit>=inp_desc->buffer+2)
+if(inp_desc->buffer[0]=='@'&&
+(inp_desc->buffer[1]=='Z'||inp_desc->buffer[1]=='z'))
+return true;
+return false;
+}
+
+
+/*:47*//*48:*/
+#line 893 "./ctie.w"
+
+boolean e_of_ch_preamble(i)
+file_index i;
+{
+register input_description*inp_desc= input_organisation[i];
+
+if(inp_desc->limit>=inp_desc->buffer+2&&inp_desc->buffer[0]=='@')
+if(inp_desc->buffer[1]=='Y'||inp_desc->buffer[1]=='y'){
+if(inp_desc->dont_match> 0){
+inp_desc->loc= inp_desc->buffer+2;
+fprintf(stderr,"\n! Hmm... %d ",inp_desc->dont_match);
+err_print(i,"of the preceding lines failed to match");
+}
+return true;
+}
+return false;
+}
+
+
+
+/*:48*//*59:*/
+#line 1105 "./ctie.w"
+
+void usage_error()
+{
+/*60:*/
+#line 1118 "./ctie.w"
+
+printf("%s\n",banner);
+printf("%s\n",copyright);
+
+
+/*:60*/
+#line 1108 "./ctie.w"
+;
+fprintf(stderr,"Usage: ctie -[mc] outfile master changefile(s)\n");
+fprintf(stderr,"Type ctie --help for more information\n");
+exit(1);
+}
+
+
+/*:59*/
+#line 95 "./ctie.w"
+
+/*3:*/
+#line 101 "./ctie.w"
+
+main(argc,argv)
+int argc;string*argv;
+{
+/*17:*/
+#line 300 "./ctie.w"
+
+actual_input= 0;
+out_mode= normal;
+
+/*:17*/
+#line 105 "./ctie.w"
+;
+/*61:*/
+#line 1135 "./ctie.w"
+
+{
+if(argc> max_file_index+5-1)usage_error();
+no_ch= -1;
+while(--argc> 0){
+argv++;
+if(strcmp("-help",*argv)==0||strcmp("--help",*argv)==0)
+/*64:*/
+#line 1202 "./ctie.w"
+
+usage_help();
+
+
+
+/*:64*/
+#line 1142 "./ctie.w"
+;
+if(strcmp("-version",*argv)==0||strcmp("--version",*argv)==0)
+/*65:*/
+#line 1208 "./ctie.w"
+
+{
+print_version_and_exit("CTIE",version_number);
+
+}
+
+
+/*:65*/
+#line 1144 "./ctie.w"
+;
+if(**argv=='-')/*62:*/
+#line 1158 "./ctie.w"
+
+if(prod_chf!=unknown)usage_error();
+else
+switch(*(*argv+1)){
+case'c':case'C':prod_chf= chf;break;
+case'm':case'M':prod_chf= master;break;
+default:usage_error();
+}
+
+
+/*:62*/
+#line 1145 "./ctie.w"
+
+else/*63:*/
+#line 1172 "./ctie.w"
+
+{
+if(no_ch==(-1)){
+out_name= *argv;
+}else{
+register input_description*inp_desc;
+
+inp_desc= (input_description*)malloc(sizeof(input_description));
+if(inp_desc==NULL)
+fatal_error(-1,"! No memory for input descriptor","");
+
+inp_desc->mode= search;
+inp_desc->line= 0;
+inp_desc->type_of_file= chf;
+inp_desc->limit= inp_desc->buffer;
+inp_desc->buffer[0]= ' ';
+inp_desc->loc= inp_desc->buffer+1;
+inp_desc->buffer_end= inp_desc->buffer+buf_size-2;
+inp_desc->file_name= *argv;
+inp_desc->current_include= NULL;
+input_organisation[no_ch]= inp_desc;
+}
+no_ch++;
+}
+
+
+/*:63*/
+#line 1146 "./ctie.w"
+
+}
+if(no_ch<=0||prod_chf==unknown)usage_error();
+}
+
+
+/*:61*/
+#line 106 "./ctie.w"
+
+/*60:*/
+#line 1118 "./ctie.w"
+
+printf("%s\n",banner);
+printf("%s\n",copyright);
+
+
+/*:60*/
+#line 107 "./ctie.w"
+;
+/*40:*/
+#line 750 "./ctie.w"
+
+{
+input_organisation[0]->the_file=
+fopen(input_organisation[0]->file_name,"r");
+
+if(input_organisation[0]->the_file==NULL)
+pfatal_error("! Cannot open master file ",
+input_organisation[0]->file_name);
+
+printf("(%s)\n",input_organisation[0]->file_name);
+input_organisation[0]->type_of_file= master;
+get_line(0,true);
+}
+
+
+/*:40*/
+#line 108 "./ctie.w"
+
+/*41:*/
+#line 768 "./ctie.w"
+
+{
+file_index i;
+
+i= 1;
+while(i<no_ch){
+input_organisation[i]->the_file=
+fopen(input_organisation[i]->file_name,"r");
+if(input_organisation[i]->the_file==NULL)
+pfatal_error("! Cannot open change file ",
+input_organisation[i]->file_name);
+
+printf("(%s)\n",input_organisation[i]->file_name);
+init_change_file(i);
+i++;
+}
+}
+
+
+/*:41*/
+#line 109 "./ctie.w"
+
+/*38:*/
+#line 729 "./ctie.w"
+
+{
+out_file= fopen(out_name,"w");
+if(out_file==NULL){
+pfatal_error("! Cannot open/create output file","");
+
+}
+}
+
+
+/*:38*/
+#line 110 "./ctie.w"
+
+/*57:*/
+#line 1074 "./ctie.w"
+
+actual_input= 0;
+input_has_ended= false;
+while(input_has_ended==false||actual_input!=0)
+/*49:*/
+#line 917 "./ctie.w"
+
+{
+file_index test_file;
+
+/*50:*/
+#line 934 "./ctie.w"
+
+{
+register input_description*inp_desc;
+while(actual_input> 0&&e_of_ch_module(actual_input)){
+inp_desc= input_organisation[actual_input];
+if(inp_desc->type_of_file==master){
+
+fatal_error(-1,"! This can't happen: change file is master file","");
+
+}
+inp_desc->mode= search;
+init_change_file(actual_input);
+while((input_organisation[actual_input]->mode!=reading
+&&actual_input> 0))
+actual_input--;
+}
+}
+
+
+/*:50*/
+#line 921 "./ctie.w"
+
+if(input_has_ended&&actual_input==0)break;
+/*51:*/
+#line 960 "./ctie.w"
+
+test_input= none;
+test_file= actual_input;
+while(test_input==none&&test_file<no_ch-1){
+test_file++;
+switch(input_organisation[test_file]->mode){
+case search:
+if(lines_dont_match(actual_input,test_file)==false){
+input_organisation[test_file]->mode= test;
+test_input= test_file;
+}
+break;
+case test:
+if(lines_dont_match(actual_input,test_file)){
+
+input_organisation[test_file]->dont_match++;
+}
+test_input= test_file;
+break;
+case reading:
+break;
+case ignore:
+break;
+}
+}
+
+
+/*:51*/
+#line 923 "./ctie.w"
+
+/*52:*/
+#line 993 "./ctie.w"
+
+if(prod_chf==chf){
+while(1){
+/*53:*/
+#line 1007 "./ctie.w"
+
+if(out_mode==normal){
+if(test_input!=none){
+fprintf(out_file,"@x\n");
+out_mode= pre;
+}else break;
+}
+
+
+/*:53*/
+#line 996 "./ctie.w"
+
+/*54:*/
+#line 1021 "./ctie.w"
+
+if(out_mode==pre){
+if(test_input==none){
+fprintf(out_file,"@y\n");
+out_mode= post;
+}else{
+if(input_organisation[actual_input]->type_of_file==master)
+put_line(actual_input);
+break;
+}
+}
+
+
+/*:54*/
+#line 997 "./ctie.w"
+
+/*55:*/
+#line 1040 "./ctie.w"
+
+if(out_mode==post){
+if(input_organisation[actual_input]->type_of_file==chf){
+if(test_input==none)put_line(actual_input);
+break;
+}else{
+fprintf(out_file,"@z\n\n");
+out_mode= normal;
+}
+}
+
+
+/*:55*/
+#line 998 "./ctie.w"
+
+}
+}else
+if(test_input==none)put_line(actual_input);
+
+
+/*:52*/
+#line 924 "./ctie.w"
+
+/*56:*/
+#line 1055 "./ctie.w"
+
+get_line(actual_input,true);
+if(test_input!=none){
+get_line(test_input,true);
+if(e_of_ch_preamble(test_input)==true){
+get_line(test_input,true);
+input_organisation[test_input]->mode= reading;
+actual_input= test_input;
+test_input= none;
+}
+}
+
+
+/*:56*/
+#line 925 "./ctie.w"
+
+}
+
+
+/*:49*/
+#line 1078 "./ctie.w"
+
+if(out_mode==post)
+fprintf(out_file,"@z\n");
+
+
+/*:57*/
+#line 111 "./ctie.w"
+
+/*58:*/
+#line 1087 "./ctie.w"
+
+{
+file_index i;
+
+for(i= 1;i<no_ch;i++){
+if(input_organisation[i]->mode!=ignore){
+input_organisation[i]->loc= input_organisation[i]->buffer;
+err_print(i,"! Change file entry did not match");
+
+}
+}
+}
+
+
+/*:58*/
+#line 112 "./ctie.w"
+
+exit(wrap_up());
+}
+
+/*:3*/
+#line 96 "./ctie.w"
+
+
+/*:2*//*68:*/
+#line 1237 "./ctie.w"
+
+void usage_help()
+{
+string*message= CTIEHELP;
+
+while(*message){
+fputs(*message,stdout);
+putchar('\n');
+++message;
+}
+putchar('\n');
+exit(0);
+}
+
+
+/*:68*//*69:*/
+#line 1252 "./ctie.w"
+
+void print_version_and_exit(name,version)
+string name,version;
+{
+printf("%s %s\n",name,version);
+
+puts("Copyright (C) 2002,2003 Julian Gilbey.");
+
+puts("There is NO warranty. This is free software. See the source");
+puts("code of CTIE for redistribution conditions.");
+
+exit(0);
+}
+
+
+/*:69*/
diff --git a/Build/source/texk/web2c/ctiedir/ctie.cf1 b/Build/source/texk/web2c/ctiedir/ctie.cf1
new file mode 100644
index 00000000000..5b1165435c9
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.cf1
@@ -0,0 +1,14 @@
+@x
+line 2
+line 3
+@y
+changed line 2
+changed line 3
+inserted line
+@z
+
+@x
+line 7
+@y
+changed line 7
+@z
diff --git a/Build/source/texk/web2c/ctiedir/ctie.cf2 b/Build/source/texk/web2c/ctiedir/ctie.cf2
new file mode 100644
index 00000000000..d9a5fbaf673
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.cf2
@@ -0,0 +1,26 @@
+@x
+line 1
+changed line 2
+changed line 3
+inserted line
+line 4
+@y
+final line 2
+final line 3
+changed line 4
+@z
+
+@x
+include line 1
+@y
+changed include line 1
+inserted include line
+@z
+
+@x
+changed line 7
+line 8
+@y
+final line 7
+final line 8
+@z
diff --git a/Build/source/texk/web2c/ctiedir/ctie.cf3 b/Build/source/texk/web2c/ctiedir/ctie.cf3
new file mode 100644
index 00000000000..95c7ff63536
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.cf3
@@ -0,0 +1,13 @@
+@x
+changed line 4
+@y
+final line 4
+@z
+
+@x
+changed include line 1
+inserted include line
+@y
+final include line 1
+@i ctie.inc2
+@z
diff --git a/Build/source/texk/web2c/ctiedir/ctie.chf.gen b/Build/source/texk/web2c/ctiedir/ctie.chf.gen
new file mode 100644
index 00000000000..d07e9280c08
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.chf.gen
@@ -0,0 +1,26 @@
+@x
+line 1
+line 2
+line 3
+line 4
+@y
+final line 2
+final line 3
+final line 4
+@z
+
+@x
+include line 1
+@y
+final include line 1
+final inserted include line
+@z
+
+@x
+line 7
+line 8
+@y
+final line 7
+final line 8
+@z
+
diff --git a/Build/source/texk/web2c/ctiedir/ctie.inc b/Build/source/texk/web2c/ctiedir/ctie.inc
new file mode 100644
index 00000000000..435c17d8a18
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.inc
@@ -0,0 +1,4 @@
+include line 1
+include line 2
+@i ctie.inc1
+include line 3
diff --git a/Build/source/texk/web2c/ctiedir/ctie.inc1 b/Build/source/texk/web2c/ctiedir/ctie.inc1
new file mode 100644
index 00000000000..79b0114e1e8
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.inc1
@@ -0,0 +1 @@
+included include line
diff --git a/Build/source/texk/web2c/ctiedir/ctie.inc2 b/Build/source/texk/web2c/ctiedir/ctie.inc2
new file mode 100644
index 00000000000..bb83f8a6710
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.inc2
@@ -0,0 +1 @@
+final inserted include line
diff --git a/Build/source/texk/web2c/ctiedir/ctie.master.gen b/Build/source/texk/web2c/ctiedir/ctie.master.gen
new file mode 100644
index 00000000000..4c00f383145
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.master.gen
@@ -0,0 +1,19 @@
+final line 2
+final line 3
+final line 4
+line 5
+final include line 1
+final inserted include line
+include line 2
+included include line
+include line 3
+line 6
+final line 7
+final line 8
+line 9
+line 10
+The character set:
+abcdefghijklmnopqrstuvwxyz
+ABCDEFGHIJKLMNOPQRSTUVWXYZ
+=!"#$%&/()?'`^~|-+[]{}@\;:
+ 0123456789<>.,*_
diff --git a/Build/source/texk/web2c/ctiedir/ctie.test b/Build/source/texk/web2c/ctiedir/ctie.test
new file mode 100755
index 00000000000..fea758881d3
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.test
@@ -0,0 +1,20 @@
+#! /bin/sh -vx
+# $Id$
+# Copyright 2017 Karl Berry <tex-live@tug.org>
+# Copyright 2009 Peter Breitenlohner <tex-live@tug.org>
+# You may freely use, modify and/or distribute this file.
+
+TEXMFCNF=$srcdir/../kpathsea \
+ CWEBINPUTS=$srcdir/ctiedir \
+ ./ctie -c ctie.outc ctie.tie ctie.cf1 ctie.cf2 ctie.cf3 || exit 1
+
+
+diff ctie.outc $srcdir/ctiedir/ctie.chf.gen || exit 1
+
+TEXMFCNF=$srcdir/../kpathsea \
+ CWEBINPUTS=$srcdir/ctiedir \
+ ./ctie -m ctie.outm ctie.tie ctie.cf1 ctie.cf2 ctie.cf3 || exit 1
+
+
+diff ctie.outm $srcdir/ctiedir/ctie.master.gen || exit 1
+
diff --git a/Build/source/texk/web2c/ctiedir/ctie.tie b/Build/source/texk/web2c/ctiedir/ctie.tie
new file mode 100644
index 00000000000..649b26d5518
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.tie
@@ -0,0 +1,16 @@
+line 1
+line 2
+line 3
+line 4
+line 5
+@i "ctie.inc"
+line 6
+line 7
+line 8
+line 9
+line 10
+The character set:
+abcdefghijklmnopqrstuvwxyz
+ABCDEFGHIJKLMNOPQRSTUVWXYZ
+=!"#$%&/()?'`^~|-+[]{}@\;:
+ 0123456789<>.,*_
diff --git a/Build/source/texk/web2c/ctiedir/ctie.w b/Build/source/texk/web2c/ctiedir/ctie.w
new file mode 100644
index 00000000000..33abf6312c8
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctie.w
@@ -0,0 +1,1280 @@
+% This is ctie.w
+% Copyright (c) 2002,2003 by Julian Gilbey
+% All rights reserved.
+%
+% This program is distributed WITHOUT ANY WARRANTY, express or implied.
+%
+% Permission is granted to make and distribute verbatim copies of this
+% program 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
+% program 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.
+%
+% This program is based heavily on tie.w and common.w, part of the
+% CWEB source.
+
+\def\title{The CTIE processor}
+\def\botofcontents{%
+\vfill
+$\copyright$ 2002,2003 Julian Gilbey
+
+All rights reserved.
+
+This program is distributed WITHOUT ANY WARRANTY, express or implied.
+
+Permission is granted to make and distribute verbatim copies of this
+program 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
+program 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.
+}
+
+
+@* Introduction.
+Whenever a programmer wants to change a given \.{WEB} or \.{CWEB}
+program (referred to as a \.{WEB} program throughout this program)
+because of system dependencies, she or he will create a new change
+file. In addition there may be a second change file to modify system
+independent modules of the program. But the \.{WEB} file cannot be
+tangled and weaved with more than one change file simultaneously.
+The \.{TIE} program was designed to merge a \.{WEB} file
+and several change files producing a new \.{WEB} file, and since the
+input files are tied together, the program was called \.{TIE}.
+Furthermore, the program could be used to merge several change files
+giving a new single change file. This method seems to be more
+important because it doesn't modify the original source file.
+
+However, the introduction of \.{CWEB} has meant that \.{TIE} is not
+quite able to perform its task correctly any longer: \.{CWEB}
+introduced the idea of include files, which are input into \.{CWEB}
+files using the \.{@@i} command, and \.{TIE} is unable to handle such
+constructs if the change files modify lines included in those files.
+The present program, \.{CTIE}, is designed to overcome this lack.
+Like \.{TIE}, upon which it is based, it can either output a single
+master \.{WEB} file or a master change file. However, in both cases,
+any include commands will be totally expanded and the files included
+in the output rather than the \.{@@i} commands being left; this makes
+this code feasible, which it would not necessarily be otherwise.
+Other than this difference, \.{CTIE} should function identically to
+\.{TIE} on files which do not involve any \.{CWEB} include commands.
+
+The algorithm used is essentially the same as that of \.{TIE}, with
+modifications to check for and handle \.{@@i} commands. Thus, as with
+\.{TIE}, the method used only needs one buffer line for each input
+file. Thus the storage requirement of \.{CTIE} does not depend on the
+sizes of the input files but only on their number.
+
+The program is written in \CEE/ and has few system dependencies.
+
+The ``banner line'' defined here should be changed whenever
+\.{CTIE} is modified. We also keep the version number here separately
+for ease; it is used below.
+
+@d version_number "1.1"
+@d banner "This is CTIE, Version 1.1"
+@d copyright
+ "Copyright 2002,2003 Julian Gilbey. All rights reserved. There is no warranty.\n\
+Run with the --version option for other important information."
+
+
+@ The main outline of the program is now given.
+This can be used more or less for any \CEE/ program.
+
+@c
+@<Global \&{\#include}s@>@;
+@<Global types@>@;
+@<Predeclaration of functions@>@;
+@<Global variables@>@;
+@<Error handling functions@>@;
+@<Internal functions@>@;
+@<The main function@>@;
+
+@ And this is the structure of the |main| function: this is where
+\.{CTIE} starts, and where it ends.
+
+@<The main function@>=
+main(argc, argv)
+ int argc; string *argv;
+{
+ @<Initialise parameters@>;
+ @<Scan the parameters@>@;
+ @<Print the banners@>;
+ @<Get the master file started@>@;
+ @<Prepare the change files@>@;
+ @<Prepare the output file@>@;
+ @<Process the input@>@;
+ @<Check that all changes have been read@>@;
+ exit(wrap_up());
+}
+
+@ We include the additional types |boolean| and |string|. \.{CTIE}
+replaces the complex \.{TIE} character set handling (based on that of
+the original \.{WEB} system) with the standard \.{CWEB} behaviour, and
+so uses the |char| type for input and output.
+
+@d false 0
+@d true 1
+
+@<Global types@>=
+typedef int boolean;
+typedef char* string;
+
+
+@ We predeclare some standard string-handling 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. (There's confusion
+between \.{<string.h>} and \.{<strings.h>}.)
+
+@<Predecl...@>=
+extern int strlen(); /* length of string */
+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 */
+extern char *strerror();
+
+
+@ The following parameters should be sufficient for most
+applications of \.{CTIE}.
+@^system dependencies@>
+
+@d buf_size 1024 /* maximum length of one input line */
+@d max_file_index 32
+/* we don't think that anyone needs more than 32 change files */
+@d xisupper(c) (isupper(c)&&((unsigned char)c<0200))
+
+
+@ We introduce a history variable that allows us to set a
+return code if the operating system can use it.
+First we introduce the coded values for the history.
+This variable must be initialized.
+(We do this even if the value given may be the default for
+variables, just to document the need for the initial value.)
+@d spotless 0
+@d troublesome 1
+@d fatal 2
+
+@<Global variables@>=
+int history=spotless;
+
+
+@* Input and output.
+Standard output for the user is done by writing on |stdout|. Error
+messages are written to |stderr|. Terminal input is not needed in
+this version of \.{CTIE}. |stdin|, |stdout| and |stderr| are
+predefined as we include the \.{stdio.h} definitions.
+
+@<Global \&{\#include}s@>=
+#include <stdio.h>
+
+
+@ And we need dynamic memory allocation.
+This should cause no trouble in any \CEE/ program.
+@^system dependencies@>
+
+@<Global \&{\#include}s@>=
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+
+@* Data structures.
+The multiple primary input files (master file and change
+files) are treated the same way. To organize the
+simultaneous usage of several input files, we introduce the
+data type \&{in\_file\_modes}.
+
+The mode |search| indicates that \.{CTIE} searches for a
+match of the input line with any line of an input file in
+|reading| mode. |test| is used whenever a match is found
+and it has to be tested if the next input lines do match
+also. |reading| describes that the lines can be read without
+any check for matching other lines. |ignore| denotes
+that the file cannot be used. This may happen because an
+error has been detected or because the end of the file has
+been found.
+
+\leavevmode |file_types| is used to describe whether a file
+is a master file or a change file. The value |unknown| is added
+to this type to set an initial mode for the output file.
+This enables us to check whether any option was used to select
+the kind of output. (this would even be necessary if we
+would assume a default action for missing options.)
+
+@<Global types@>=
+#define search 0
+#define test 1
+#define reading 2
+#define ignore 3
+typedef int in_file_modes; /* should be |enum(search, test, reading, ignore)| */
+#define unknown 0
+#define master 1
+#define chf 2
+typedef int file_types; /* should be |enum(unknown, master, chf)| */
+
+
+@ A variable of type |out_md_type| will tell us in what state the output
+change file is during processing. |normal| will be the state, when we
+did not yet start a change, |pre| will be set when we write the lines
+to be changes and |post| will indicate that the replacement lines are
+written.
+
+@<Global types@>=
+#define normal 0
+#define pre 1
+#define post 2
+typedef int out_md_type; /* should be |enum(normal, pre, post)| */
+
+
+@ The next type will indicate variables used as an index into the file
+table.
+
+@<Global types@>=
+typedef int file_index; /* |-1..max_file_index+1| */
+
+
+@ This is the data structure in which we collect information about
+each include file.
+
+@<Global types@>=
+typedef struct _indsc {
+ char file_name[max_file_name_length];
+ long line;
+ FILE *the_file;
+ struct _indsc *parent;
+} include_description;
+
+
+@ The following data structure contains all of the information needed
+to use these input files.
+%`line' is a normal identifier throughout this program
+@f line dummy
+@<Global types@>=
+typedef struct _idsc{
+ string file_name;
+ char buffer[buf_size];
+ in_file_modes mode;
+ long line;
+ file_types type_of_file;
+ include_description *current_include;
+ char *buffer_end;
+ char *limit;
+ char *loc;
+ FILE *the_file;
+ int dont_match;
+ } input_description;
+
+
+@ Every one of the primary input files might include another file
+using the \.{@@i} include mechanism. In turn, each of these might
+include other files, and so on. We allow a limited number of these
+files to be opened simultaneously, and we store information about the
+currently open include files as a linked list attached to each primary
+file.
+
+@d max_include_files 20
+ /* maximum number of include files open simultaneously */
+@d max_file_name_length 60
+
+@<Global variables@>=
+int total_include_files = 0; /* count 'em */
+
+@ The following variables refer to the files in action, the number of
+change files, the mode of operation and the current output state.
+
+@<Global variables@>=
+file_index actual_input, test_input, no_ch;
+file_types prod_chf=unknown;
+out_md_type out_mode;
+
+@ And the |actual_input| and |out_mode| variables need to be
+initialised sensibly.
+
+@<Initialise parameters@>=
+actual_input=0;
+out_mode=normal;
+
+@ All primary input files (including the master file) are recorded
+in the following structure.
+The components are usually accessed through a local pointer variable,
+requiring only a one-time-computation of the index expression.
+
+@<Global variables@>=
+input_description *input_organisation[max_file_index+1];
+
+
+@* File I/O.
+The basic function |get_line| can be used to get a line from
+an input file. The line is stored in the |buffer| part of the
+descriptor. The components |limit| and |line| are updated. If the
+end of the file is reached |mode| is set to |ignore|. On some systems
+it might be useful to replace tab characters by a proper number of
+spaces since several editors used to create change files insert tab
+characters into a source file not under control of the user. So it
+might be a problem to create a matching change file.
+@^tab character expansion@>
+
+We define |get_line| to read a line from a file specified by the
+corresponding file descriptor. This function returns |true| if it is
+successful and |false| if the end of the file has been reached.
+
+@<Internal functions@>=
+boolean get_line(i, do_includes)
+ file_index i; boolean do_includes;
+{
+ register input_description *inp_desc=input_organisation[i];
+ register FILE *fp;
+
+ if (inp_desc->mode==ignore) return false;
+
+ restart:
+ if (inp_desc->current_include != NULL) {
+ register include_description *inc_desc=inp_desc->current_include;
+
+ fp=inc_desc->the_file;
+ @<Get include line into buffer or |goto restart| if end of file@>@;
+ }
+ else {
+ fp=inp_desc->the_file;
+ @<Get line into buffer, |return false| if end of file@>@;
+ }
+
+ if (do_includes)
+ @<Check for \.{@@i} in newly read line, |goto restart| if
+ include fails@>@;
+ return true;
+}
+
+
+@ Lines must fit into the buffer completely.
+We read all characters sequentially until an end of line is found
+(but do not forget to check for |EOF|!).
+Too long input lines will be truncated.
+This will result in a damaged output if they occur in the
+replacement part of a change file, or in an incomplerte check if the
+matching part is concerned.
+Tab character expansion might be done here.
+@^tab character expansion@>
+
+@<Get line into buffer,...@>=
+{
+ register int c; /* the actual character read */
+ register char *k; /* where the next character goes */
+
+ if (feof(fp))
+ @<Handle end of file and return@>@;
+
+ inp_desc->limit = k = inp_desc->buffer; /* beginning of buffer */
+ while (k<=inp_desc->buffer_end && (c=getc(fp)) != EOF && c!='\n')
+ if ((*(k++) = c) != ' ') inp_desc->limit = k;
+ if (k>inp_desc->buffer_end)
+ if ((c=getc(fp))!=EOF && c!='\n') {
+ ungetc(c, fp); inp_desc->loc=inp_desc->buffer;
+ err_print(i, "! Input line too long");
+@.Input line too long@>
+ }
+ if (c==EOF && inp_desc->limit==inp_desc->buffer)
+ @<Handle end of file...@>@;
+
+ @<Increment the line number and print a progess report at
+ certain times@>@;
+}
+
+
+@ End of file is special if this file is the master file.
+Then we set the global flag variable |input_has_ended|.
+
+@<Handle end of file ...@>=
+{
+ inp_desc->mode=ignore;
+ inp_desc->limit=NULL; /* mark end-of-file */
+ if (inp_desc->type_of_file==master) input_has_ended=true;
+ fclose(fp);
+ return false;
+}
+
+
+@ This variable must be declared for global access.
+
+@<Global variables@>=
+boolean input_has_ended=false;
+
+
+@ This section does what its name says. Every 100 lines
+in the master file we print a dot, every 500 lines the number
+of lines is shown.
+
+@<Increment the line number and print ...@>=
+inp_desc->line++;
+if (inp_desc->type_of_file==master && inp_desc->line % 100==0) {
+ if (inp_desc->line % 500 == 0) printf("%ld", inp_desc->line);
+ else putchar('.');
+ fflush(stdout);
+}
+
+
+@ The following is very similar to the above, but for the case where
+we are reading from an include file.
+
+@<Get include line into buffer or |goto restart| if end of file@>=
+{
+ register int c; /* the actual character read */
+ register char *k; /* where the next character goes */
+
+ if (feof(fp))
+ @<Handle end of include file and |goto restart|@>@;
+
+ inp_desc->limit = k = inp_desc->buffer; /* beginning of buffer */
+ while (k<=inp_desc->buffer_end && (c=getc(fp)) != EOF && c!='\n')
+ if ((*(k++) = c) != ' ') inp_desc->limit = k;
+ if (k>inp_desc->buffer_end)
+ if ((c=getc(fp))!=EOF && c!='\n') {
+ ungetc(c, fp); inp_desc->loc=inp_desc->buffer;
+ err_print(i, "! Input line too long");
+@.Input line too long@>
+ }
+ if (c==EOF && inp_desc->limit==inp_desc->buffer)
+ @<Handle end of include file...@>@;
+
+ inc_desc->line++;
+}
+
+@ We don't bail out if we find the end of an include file, we just
+return to the parent file.
+
+@<Handle end of include file and |goto restart|@>=
+{
+ include_description *temp=inc_desc->parent;
+
+ fclose(fp);
+ free(inc_desc);
+ total_include_files--;
+ inp_desc->current_include=temp;
+ goto restart;
+}
+
+
+@ Usually, we have to check the line we have just read to see whether
+it begins with \.{@@i} and therefore needs expanding.
+
+@<Check for \.{@@i} in newly read line...@>=
+{
+ inp_desc->loc=inp_desc->buffer;
+ *inp_desc->limit=' ';
+ if (*inp_desc->buffer=='@@' &&
+ (inp_desc->buffer[1]=='i' || inp_desc->buffer[1]=='I')) {
+ inp_desc->loc=inp_desc->buffer+2;
+ *inp_desc->limit='"'; /* this will terminate the search in all cases */
+ while (*inp_desc->loc==' '||*inp_desc->loc=='\t')
+ inp_desc->loc++;
+ if (inp_desc->loc>=inp_desc->limit) {
+ err_print(i, "! Include file name not given");
+@.Include file name ...@>
+ goto restart;
+ }
+ if (total_include_files>=max_include_files) {
+ err_print(i, "! Too many nested includes");
+@.Too many nested includes@>
+ goto restart;
+ }
+ total_include_files++; /* push input stack */
+ @<Try to open include file, abort push if unsuccessful, go to |restart|@>;
+ }
+}
+
+
+@ When an \.{@@i} line is found in the 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() {total_include_files--; free(new_inc);
+ err_print(i, "! Include file name too long"); goto restart;}
+
+@<Try to open...@>=
+{
+ include_description *new_inc;
+ char temp_file_name[max_file_name_length];
+ char *file_name_end;
+ char *k, *kk;
+ int l; /* length of file name */
+
+ new_inc=(include_description *) malloc(sizeof(include_description));
+ if (new_inc==NULL)
+ fatal_error(i, "! No memory for new include descriptor", "");
+ new_inc->line=0;
+ k=new_inc->file_name;
+ file_name_end=k+max_file_name_length-1;
+
+ if (*inp_desc->loc=='"') {
+ inp_desc->loc++;
+ while (*inp_desc->loc!='"' && k<=file_name_end)
+ *k++=*inp_desc->loc++;
+ if (inp_desc->loc==inp_desc->limit)
+ k=file_name_end+1; /* unmatched quote is `too long' */
+ } else
+ while (*inp_desc->loc!=' '&&*inp_desc->loc!='\t'&&
+ *inp_desc->loc!='"'&&k<=file_name_end) *k++=*inp_desc->loc++;
+ if (k>file_name_end) too_long();
+@.Include file name ...@>
+ *k='\0';
+ if ((new_inc->the_file=fopen(new_inc->file_name, "r"))!=NULL) {
+ new_inc->parent=inp_desc->current_include; /* link it in */
+ inp_desc->current_include=new_inc;
+ 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>=file_name_end) too_long();
+ for (; k>= new_inc->file_name; k--) *(k+l+1)=*k;
+ strcpy(new_inc->file_name, temp_file_name);
+ new_inc->file_name[l]='/'; /* \UNIX/ pathname separator */
+ if ((new_inc->the_file=fopen(new_inc->file_name, "r"))!=NULL) {
+ new_inc->parent=inp_desc->current_include; /* link it in */
+ inp_desc->current_include=new_inc;
+ goto restart; /* success */
+ }
+ }
+ total_include_files--;
+ free(new_inc);
+ err_print(i, "! Cannot open include file");
+@.Cannot open include file@>
+ goto restart;
+}
+
+
+
+@* Reporting errors to the user.
+There may be errors if a line in a given change
+file does not match a line in the master file or a
+replacement in a previous change file. Such errors are
+reported to the user by saying
+$$
+ \hbox{|err_print(file_no, "! Error message")|;}
+$$
+where |file_no| is the number of the file which is concerned by the
+error. Please note that no trailing dot is supplied in the error
+message because it is appended by |err_print|.
+
+@<Predecl...@>=
+void err_print();
+
+@ Here is the outline of the |err_print| function.
+
+@<Error handling...@>=
+void err_print(i, s) /* prints `\..' and location of error message */
+file_index i; char *s;
+{
+ char *k, *l; /* pointers into an appropriate |buffer| */
+ fprintf(stderr, *s=='!'? "\n%s" : "%s", s);
+ if(i>=0) @<Print error location based on input buffer@>@;
+ else putc('\n', stderr);
+ fflush(stderr);
+ history=troublesome;
+}
+
+@ The error locations can be indicated by using the variables
+|loc|, |line| and |file_name| within the appropriate file description
+structures, which tell respectively the first
+unlooked-at position in the |buffer|, the current line number and the
+current file. We can determine whether we are looking at an included
+file or not by examining the |current_include| variable.
+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@>=
+{
+ register input_description *inp_desc=input_organisation[i];
+ register include_description *inc_desc=inp_desc->current_include;
+
+ if (inc_desc!=NULL) {
+ fprintf(stderr, ". (l. %ld of include file %s", inc_desc->line,
+ inc_desc->file_name);
+ fprintf(stderr, " included from l. %ld of %s file %s)\n",
+ inp_desc->line,
+ inp_desc->type_of_file==master?"master":"change",
+ inp_desc->file_name);
+ }
+ else
+ fprintf(stderr, ". (l. %ld of %s file %s)\n", inp_desc->line,
+ inp_desc->type_of_file==master?"master":"change",
+ inp_desc->file_name);
+ l=(inp_desc->loc>=inp_desc->limit? inp_desc->limit: inp_desc->loc);
+ if (l>inp_desc->buffer) {
+ for (k=inp_desc->buffer; k<l; k++)
+ if (*k=='\t') putc(' ', stderr);
+ else putc(*k, stderr); /* print the characters already read */
+ putc('\n', stderr);
+ for (k=inp_desc->buffer; k<l; k++)
+ putc(' ', stderr); /* space out the next line */
+ }
+ for (k=l; k<inp_desc->limit; k++)
+ putc(*k, stderr); /* print the part not yet read */
+ putc('\n', stderr);
+}
+
+
+@ Non recoverable errors are handled by calling |fatal_error| that
+outputs a message and then calls `|wrap_up|' and exits. |err_print|
+will print the error message followed by an indication of where the
+error was spotted in the source files. |fatal_error| cannot state any
+files because the problem is usually to access these.
+
+@d fatal_error(i, s, t) {
+ fprintf(stderr, "\n%s", s);
+ err_print(i, t);
+ history=fatal;
+ exit(wrap_up());
+ }
+
+
+@ 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@>
+
+@<Internal func...@>=
+int wrap_up()
+{
+ @<Print the job |history|@>;
+ if (history > spotless) return 1;
+ else return 0;
+}
+
+@ Always good to prototype.
+
+@<Predecl...@>=
+int wrap_up();
+
+@ We report the history to the user, although this may not
+be ``\UNIX/'' style---but we are in good company: \.{WEB} and
+\TEX/ do the same. We put this on |stdout| rather than |stderr|, so
+that users can easily filter this away if they wish.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+switch (history) {
+ case spotless:
+ printf("\n(No errors were found.)\n"); break;
+ case troublesome:
+ printf("\n(Pardon me, but I think I spotted something wrong.)\n"); break;
+ case fatal: printf("(That was a fatal error, my friend.)\n");
+} /* there are no other cases */
+
+
+@ If there's a system error, we may be able to give the user more
+information with the |pfatal_error| function. This prints out system
+error information if it is available.
+
+@<Predecl...@>=
+void pfatal_error();
+
+@ @<Error handling...@>=
+void pfatal_error(s, t)
+char *s, *t;
+{
+ char *strerr=strerror(errno);
+
+ fprintf(stderr, "\n%s%s", s, t);
+ if (strerr) fprintf(stderr, " (%s)\n", strerr);
+ else fprintf(stderr, "\n");
+ history=fatal;
+ exit(wrap_up());
+}
+
+
+@ We need an include file for the above.
+
+@<Global \&{\#include}s@>=
+#include <errno.h>
+
+
+@* Handling multiple change files.
+In the standard version we take the name of the
+files from the command line.
+It is assumed that filenames can be used as given in the
+command line without changes.
+
+First there are some sections to open all files.
+If a file is not accessible, the run will be aborted.
+Otherwise the name of the open file will be displayed.
+
+@<Prepare the output file@>=
+{
+ out_file=fopen(out_name, "w");
+ if (out_file==NULL) {
+ pfatal_error("! Cannot open/create output file", "");
+@.Cannot open/create output file@>
+ }
+}
+
+
+@ The name of the file and the file desciptor are stored in
+global variables.
+
+@<Global variables@>=
+FILE *out_file;
+string out_name;
+
+
+@ For the master file we start by reading its first line into the
+buffer, if we could open it.
+
+@<Get the master file started@>=
+{
+ input_organisation[0]->the_file=
+ fopen(input_organisation[0]->file_name, "r");
+
+ if (input_organisation[0]->the_file==NULL)
+ pfatal_error("! Cannot open master file ",
+ input_organisation[0]->file_name);
+@.Cannot open master file@>
+ printf("(%s)\n", input_organisation[0]->file_name);
+ input_organisation[0]->type_of_file=master;
+ get_line(0, true);
+}
+
+
+@ For the change files we must skip any comment part and see whether
+there are any changes in it. This is done by |init_change_file|.
+
+@<Prepare the change files@>=
+{
+ file_index i;
+
+ i=1;
+ while (i<no_ch) {
+ input_organisation[i]->the_file=
+ fopen(input_organisation[i]->file_name, "r");
+ if (input_organisation[i]->the_file==NULL)
+ pfatal_error("! Cannot open change file ",
+ input_organisation[i]->file_name);
+@.Cannot open change file@>
+ printf("(%s)\n", input_organisation[i]->file_name);
+ init_change_file(i);
+ i++;
+ }
+}
+
+
+@*Input/output organisation.
+Here's a simple function that checks if two lines
+are different.
+
+@<Internal functions@>=
+boolean lines_dont_match(i, j)
+ file_index i, j;
+{
+ register input_description *iptr=input_organisation[i],
+ *jptr=input_organisation[j];
+
+ if (iptr->limit-iptr->buffer != jptr->limit-jptr->buffer)
+ return true;
+ return strncmp(iptr->buffer, jptr->buffer, iptr->limit-iptr->buffer);
+}
+
+
+@ Function |init_change_file(i)| is used to ignore all
+lines of the input file with index~|i| until the next change
+module is found.
+
+@<Internal functions@>=
+void init_change_file(i)
+ file_index i;
+{
+ register input_description *inp_desc=input_organisation[i];
+ char ccode;
+
+ inp_desc->limit=inp_desc->buffer;
+ @<Skip over comment lines; |return| if end of file@>@;
+ @<Skip to the next nonblank line; |return| if end of file@>@;
+ inp_desc->dont_match=0;
+}
+
+
+@ 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...@>=
+while(1) {
+ if (!get_line(i, false)) return; /* end of file reached */
+ if (inp_desc->limit<inp_desc->buffer+2) continue;
+ if (inp_desc->buffer[0]!='@@') continue;
+ ccode=inp_desc->buffer[1];
+ if (xisupper(ccode)) ccode=tolower(ccode);
+ if (ccode=='x') break;
+ if (ccode=='y' || ccode=='z' || ccode=='i') {
+ inp_desc->loc=inp_desc->buffer+2;
+ err_print(i, "! Missing @@x in change file");
+@.Missing @@x...@>
+ }
+}
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do {
+ if (!get_line(i, true)) {
+ err_print(i, "! Change file ended after @@x");
+@.Change file ended...@>
+ return;
+ }
+} while (inp_desc->limit==inp_desc->buffer);
+
+
+@ The |put_line| function is used to write a line from
+input buffer |j| to the output file.
+
+@<Internal functions@>=
+void put_line(j)
+ file_index j;
+{
+ char *ptr=input_organisation[j]->buffer;
+ char *lmt=input_organisation[j]->limit;
+
+ while(ptr<lmt) putc(*ptr++, out_file);
+ putc('\n', out_file);
+}
+
+
+@ The function |e_of_ch_module| returns true if the input
+line from file |i| starts with \.{@@z}.
+
+@<Internal functions@>=
+boolean e_of_ch_module(i)
+ file_index i;
+{
+ register input_description *inp_desc=input_organisation[i];
+
+ if (inp_desc->limit==NULL) {
+ err_print(i, "! Change file ended without @@z");
+@.Change file ended without @@z@>
+ return true;
+ } else if (inp_desc->limit>=inp_desc->buffer+2)
+ if (inp_desc->buffer[0]=='@@' &&
+ (inp_desc->buffer[1]=='Z' || inp_desc->buffer[1]=='z'))
+ return true;
+ return false;
+}
+
+
+@ The function |e_of_ch_preamble| returns |true| if the input
+line from file~|i| starts with \.{@@y}.
+
+@<Internal functions@>=
+boolean e_of_ch_preamble(i)
+ file_index i;
+{
+ register input_description *inp_desc=input_organisation[i];
+
+ if (inp_desc->limit>=inp_desc->buffer+2 && inp_desc->buffer[0]=='@@')
+ if (inp_desc->buffer[1]=='Y'||inp_desc->buffer[1]=='y') {
+ if (inp_desc->dont_match>0) {
+ inp_desc->loc=inp_desc->buffer+2;
+ fprintf(stderr, "\n! Hmm... %d ", inp_desc->dont_match);
+ err_print(i, "of the preceding lines failed to match");
+ }
+ return true;
+ }
+ return false;
+}
+
+
+
+@ To process the input file the next section reads a line of the
+current (actual) input file and updates the |input_organisation| for
+all files with index greater than |actual_input|.
+
+@<Process a line, |break| when end of source reached@>=
+{
+ file_index test_file;
+
+ @<Check the current files for any ends of changes@>@;
+ if (input_has_ended && actual_input==0) break; /* all done */
+ @<Scan all other files for changes to be done@>@;
+ @<Handle output@>@;
+ @<Step to next line@>@;
+}
+
+
+@ Any of the current change files may have reached the end of the
+current change. In such a case, intermediate lines must be skipped
+and the next start of change is to be found. This may make a change
+file become inactive if the end of the file is reached.
+
+@<Check the...@>=
+{
+ register input_description *inp_desc;
+ while (actual_input>0 && e_of_ch_module(actual_input)) {
+ inp_desc=input_organisation[actual_input];
+ if (inp_desc->type_of_file==master) {
+ /* emergency exit, everything mixed up!*/
+ fatal_error(-1, "! This can't happen: change file is master file", "");
+@.This can't happen...@>
+ }
+ inp_desc->mode=search;
+ init_change_file(actual_input);
+ while ((input_organisation[actual_input]->mode!=reading
+ && actual_input>0))
+ actual_input--;
+ }
+}
+
+
+@ Now we will set |test_input| to the first change file that is being
+tested against the current line. If no other file is testing, then
+|actual_input| refers to a line to write and |test_input| is set to
+|none|.
+
+@d none (-1)
+
+@<Scan all other files...@>=
+test_input=none;
+test_file=actual_input;
+while (test_input==none && test_file<no_ch-1){
+ test_file++;
+ switch (input_organisation[test_file]->mode) {
+ case search:
+ if (lines_dont_match(actual_input, test_file)==false) {
+ input_organisation[test_file]->mode=test;
+ test_input=test_file;
+ }
+ break;
+ case test:
+ if (lines_dont_match(actual_input, test_file)) {
+ /* error, sections do not match; just note at this point */
+ input_organisation[test_file]->dont_match++;
+ }
+ test_input=test_file;
+ break;
+ case reading: /* this can't happen */
+ break;
+ case ignore: /* nothing to do */
+ break;
+ }
+}
+
+
+@ For the output we must distinguish between whether we are creating a
+new change file or a new master file. Change file creation requires
+closer inspection because we may be before a change, in the pattern
+(match) part or in the replacement part. For master file creation, we
+simply have to write the line from the current (actual) input.
+
+@<Handle output@>=
+if (prod_chf==chf) {
+ while(1) {
+ @<Test for |normal|, |break| when done@>@;
+ @<Test for |pre|, |break| when done@>@;
+ @<Test for |post|, |break| when done@>@;
+ }
+} else
+ if (test_input==none) put_line(actual_input);
+
+
+@ Check whether we have to start a change file entry.
+Without a match nothing needs to be done.
+
+@<Test for |normal|...@>=
+if (out_mode==normal) {
+ if (test_input!=none) {
+ fprintf(out_file, "@@x\n");
+ out_mode=pre;
+ } else break;
+}
+
+
+@ Check whether we have to start the replacement text. This is the
+case when we are in |pre| mode but have no more matching lines.
+Otherwise the master file source line must be copied to the change
+file.
+
+@<Test for |pre|...@>=
+if (out_mode==pre) {
+ if (test_input==none) {
+ fprintf(out_file, "@@y\n");
+ out_mode=post;
+ } else {
+ if (input_organisation[actual_input]->type_of_file==master)
+ put_line(actual_input);
+ break;
+ }
+}
+
+
+@ Check whether an entry from a change file is complete. If the
+current input is from a change file which is not being tested against
+a later change file, then this change file line must be written. If
+the actual input has been reset to the master file, we can finish this
+change.
+
+@<Test for |post|...@>=
+if (out_mode==post) {
+ if (input_organisation[actual_input]->type_of_file==chf) {
+ if (test_input==none) put_line(actual_input);
+ break;
+ } else {
+ fprintf(out_file, "@@z\n\n");
+ out_mode=normal;
+ }
+}
+
+
+@ If we had a change, we must proceed in the actual file
+to be changed and in the change file in effect.
+
+@<Step to next line@>=
+get_line(actual_input, true);
+if (test_input!=none) {
+ get_line(test_input, true);
+ if (e_of_ch_preamble(test_input)==true) {
+ get_line(test_input, true); /* update current changing file */
+ input_organisation[test_input]->mode=reading;
+ actual_input=test_input;
+ test_input=none;
+ }
+}
+
+
+@ To create the new output file we have to scan the whole
+master file and all changes in effect when it ends.
+At the very end it is wise to check for all changes
+to have completed, in case the last line of the master file
+was to be changed.
+
+@<Process the input@>=
+actual_input=0;
+input_has_ended=false;
+while (input_has_ended==false||actual_input!=0)
+ @<Process a line...@>@;
+if (out_mode==post) /* last line has been changed */
+ fprintf(out_file, "@@z\n");
+
+
+@ 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 the master file or any of the change files.
+
+@<Check that all changes have been read@>=
+{
+ file_index i;
+
+ for (i=1;i<no_ch;i++) { /* all change files */
+ if (input_organisation[i]->mode!=ignore) {
+ input_organisation[i]->loc=input_organisation[i]->buffer;
+ err_print(i, "! Change file entry did not match");
+@.Change file entry ...@>
+ }
+ }
+}
+
+
+@ We want to tell the user about our command line options if they made
+a mistake. This is done by the |usage_error()| function. It contains
+merely the necessary print statements and exits afterwards.
+
+@<Intern...@>=
+void usage_error()
+{
+ @<Print the banners@>;
+ fprintf(stderr, "Usage: ctie -[mc] outfile master changefile(s)\n");
+ fprintf(stderr, "Type ctie --help for more information\n");
+ exit(1);
+}
+
+
+@ Printing our welcome banners; we only do this if we are not asked
+for version or help information.
+
+@<Print the banners@>=
+printf("%s\n", banner); /* print a ``banner line'' */
+printf("%s\n", copyright); /* include the copyright notice */
+
+
+@ We must scan through the list of parameters, given in |argv|. The
+number is in |argc|. We must pay attention to the flag parameter. We
+need at least 3~parameters (\.{-m} or \.{-c}, an output file and a
+master file) and can handle up to |max_file_index| change files. The
+names of the file parameters will be inserted into the structure of
+|input_organisation|. The first file is special. It indicates the
+output file. When we allow flags at any position, we must find out
+which name is for what purpose. The master file is already part of
+the |input_organisation| structure (index~0). As long as the number
+of files found (counted in |no_ch|) is |-1| we have not yet found the
+output file name.
+
+@<Scan the parameters@>=
+{
+ if (argc>max_file_index+5-1) usage_error();
+ no_ch = -1; /* fill this part of |input_organisation| */
+ while (--argc>0) {
+ argv++;
+ 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@>;
+ if (**argv=='-') @<Set a flag@>@;
+ else @<Get a file name@>@;
+ }
+ if (no_ch<=0|| prod_chf==unknown) usage_error();
+}
+
+
+@ The flag is about to determine the processing mode.
+We must make sure that this flag has not been set before.
+Further flags might be introduced to avoid/force overwriting of
+output files.
+Currently we just have to set the processing flag properly.
+
+@<Set a flag@>=
+if (prod_chf!=unknown) usage_error();
+else
+ switch (*(*argv+1)) {
+ case 'c': case 'C': prod_chf=chf; break;
+ case 'm': case 'M': prod_chf=master; break;
+ default: usage_error();
+ }
+
+
+@ We have to distinguish whether this is the very first file name
+(which is the case if |no_ch==(-1)|) or if the next element of
+|input_organisation| must be filled.
+
+@<Get a file name@>=
+{
+ if (no_ch==(-1)) {
+ out_name=*argv;
+ } else {
+ register input_description *inp_desc;
+
+ inp_desc=(input_description *) malloc(sizeof(input_description));
+ if (inp_desc==NULL)
+ fatal_error(-1, "! No memory for input descriptor", "");
+@.No memory for descriptor@>
+ inp_desc->mode=search;
+ inp_desc->line=0;
+ inp_desc->type_of_file=chf;
+ inp_desc->limit=inp_desc->buffer;
+ inp_desc->buffer[0]=' ';
+ inp_desc->loc=inp_desc->buffer+1;
+ inp_desc->buffer_end=inp_desc->buffer+buf_size-2;
+ inp_desc->file_name=*argv;
+ inp_desc->current_include=NULL;
+ input_organisation[no_ch]=inp_desc;
+ }
+ no_ch++;
+}
+
+
+@ Modules for dealing with help messages and version info. We follow
+the \.{kpathsea} standard code here, so that we can easily adapt this
+to work with \.{kpathsea}.
+
+@<Display help message and exit@>=
+usage_help();
+@.--help@>
+
+
+@
+@<Display version information and exit@>=
+{
+ print_version_and_exit("CTIE", version_number);
+@.--version@>
+}
+
+
+@ Here is the usage information for \.{--help}.
+
+@<Global variables@>=
+string CTIEHELP[] = {
+ "Usage: ctie -[mc] outfile master changefile(s)",
+ " Create a new master file or change file from the given",
+ " master (C)WEB file and changefiles.",
+ " All filenames are taken literally; no suffixes are added.",
+ "",
+ "-m create a new master file from original (C)WEB and change file(s)",
+ "-c create a master change file for original (C)WEB file from changefile(s)",
+ "--help display this help and exit",
+ "--version display version information and exit",
+ NULL
+};
+
+
+@ @<Predec...@>=
+void usage_help();
+void print_version_and_exit();
+
+
+@ @c
+void usage_help()
+{
+ string *message=CTIEHELP;
+
+ while (*message) {
+ fputs(*message, stdout);
+ putchar('\n');
+ ++message;
+ }
+ putchar('\n');
+ exit(0);
+}
+
+
+@ @c
+void print_version_and_exit(name, version)
+ string name, version;
+{
+ printf ("%s %s\n", name, version);
+
+ puts ("Copyright (C) 2002,2003 Julian Gilbey.");
+
+ puts ("There is NO warranty. This is free software. See the source");
+ puts ("code of CTIE for redistribution conditions.");
+
+ exit (0);
+}
+
+
+@* System-dependent changes.
+This section should be replaced, if necessary, by
+changes to the program that are necessary to make \.{CTIE}
+work at a particular installation. It is usually best to
+design your change file so that all changes to previous
+modules preserve the module numbering; then everybody's
+version will be consistent with the printed program. More
+extensive changes, which introduce new modules, can be
+inserted here; then only the index itself will get a new
+module number.
+@^system dependencies@>
+
+
+@* Index.
diff --git a/Build/source/texk/web2c/ctiedir/ctiedoc.tex b/Build/source/texk/web2c/ctiedir/ctiedoc.tex
new file mode 100644
index 00000000000..972bfff44d4
--- /dev/null
+++ b/Build/source/texk/web2c/ctiedir/ctiedoc.tex
@@ -0,0 +1,242 @@
+% ctiedoc.tex Jan 2002, last updated Apr 2003
+%-----------------------------------------------
+
+% A minor rewrite of tiedoc.tex for the CTIE changes.
+
+
+\documentclass{article}
+
+\let\mc=\small
+\def\CEE/{{\mc C\spacefactor1000}}
+\let\.=\texttt
+
+\begin{document}
+
+\begin{center}
+\Large The \.{CTIE} Processor
+
+\bigskip
+\large
+Julian Gilbey\\
+\.{jdg@debian.org}
+
+\bigskip
+Based on the original \.{TIE} documentation by:\\
+Klaus Guntermann\\
+TH Darmstadt\\
+Fachbereich Informatik\\
+Institut f\"ur Theoretische Informatik
+
+\bigskip
+January 2002, updated April 2003
+
+\end{center}
+
+\bigskip
+
+\section{Introduction}
+
+When installing a program on a particular computer system, certain
+system dependent changes are often needed. The original \.{WEB}
+programs (\.{WEAVE} and \.{TANGLE}) handled this problem by using
+\textit{change files}, which work very much like a patch file and are
+read by \.{WEAVE} and \.{TANGLE} along with the main \.{WEB} file.
+This allows the original \.{WEB} file to remain intact and the
+particular system dependencies to be isolated.
+
+Sometimes it is good practice to develop a set of multiple change
+files for a given \.{WEB} file to distinguish between different
+changes such as program enhancements, bug fixes, system dependent
+changes and output device dependent modifications. Additionally this
+allows combinations of changes that can be used with a set of programs
+that share some common features, such as \.{WEAVE} and \.{TANGLE}
+themselves.
+
+Unfortunately, the processors \.{TANGLE} and \.{WEAVE} can handle only
+one change file. Rather than modifying these processors to handle
+multiple change files, it is easier to combine them in a preprocessing
+step. The \.{TIE} processor was written to perform this task. It is
+able to create either a new master file or a single change file that
+comprises the effect of all change files.
+
+The \.{CWEB} system was later developed in order to open up the
+\.{WEB} system of literate programming to \CEE/ programmers. It
+functions in an essentially identical way to the original Pascal
+\.{WEB} system, and the syntax of change files is the same. So it
+should be possible to use the \.{TIE} processor for \.{CWEB} source
+files. However, one significant enhancement was made to \.{CWEB}
+which makes this sometimes impossible. \.{CWEB} supports
+\textit{include files}, which are introduced by a line beginning
+`\.{@i} \textit{filename}', which includes the \.{CWEB} file
+specified, just like the \CEE/ preprocessor command \.{\#include}. As
+these include commands are effectively expanded before the change file
+is applied, both in the master file and the change file, it is clear
+that \.{TIE} needs to interpret \.{@i} commands in order to work for
+all \.{CWEB} files. Thus \.{CTIE} was born: it essentially combines
+the traditional behaviour of \.{TIE} with the ability to handle
+\.{CWEB} include files.
+
+
+\section{Application}
+
+The current version of \.{CTIE} accepts a master file and up to
+32~change files. In general it is important to use the change files
+in the correct sequence, as later change files may modify the results
+of applying earlier changes. Thus the order of the change files on
+the command line is taken to specify the order in which the change
+files should be applied. Conceptually, each change file is applied to
+the master file in turn to create a new master file, to which the next
+change file is applied; in practice, though, a more space-efficient
+algorithm is used which only requires storage space for one line per
+file, so the lengths of the individual files or changes are irrelevant
+for storage requirements.
+
+Note that \.{CTIE} will expand all \.{@i} include lines, including the
+specified files whether or not they are modified by any change files.
+So another application of \.{CTIE} is to simply expand all of these
+include files, producing an expanded master file. (Thanks to Hartmut
+Henkel \.{<hartmut\_henkel@gmx.de>} for this observation.)
+
+\.{CTIE} must be called with at least 3~parameters as follows:
+$$\texttt{ctie -[cm] outfile master changefile(s)}$$
+where the parameters are (in order):
+\begin{enumerate}
+
+\item Either the option \.{-c} or \.{-m}. This option determines
+ whether an amalgamated change file or a new master file is created.
+
+\item The name of the output file.
+
+\item The name of the master file.
+
+\item The name(s) of the change file(s), if any.
+
+\end{enumerate}
+
+Unlike the \.{CWEB} programs \.{CWEAVE} and \.{CTANGLE}, no attempt to
+add default suffixes such as \.{.w} or \.{.ch} is made; the filenames
+must be the full filenames. If \.{CTIE} has been compiled with
+\.{kpathsea} support, then the \.{kpathsea} library will be used to
+search for the files using the \.{CWEBINPUTS} variable, otherwise just
+the current directory and the directory specified by the
+\.{CWEBINPUTS} environment variable will be searched, in that order.
+
+Also, \.{CTIE} can be called with the single argument \.{--help} or
+\.{--version} to get basic help or version information.
+
+\clearpage
+
+
+\def\eof{$\langle$\textrm{\mc EOF}$\rangle$}
+\tabcolsep=1em
+\parindent=0pt
+
+\section{Example}
+
+To illustrate the actions \.{CTIE} performs you may inspect the
+following example that exercises some of the borderline cases.
+
+\begin{center}
+\ttfamily
+\begin{tabular}{llll}
+\multicolumn1{c}{\textbf{\textrm{ctie.tie}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.cf1}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.cf2}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.cf3}}}\\[1pt]
+\hline
+line 1 &@x &@x &@x\\
+line 2 &line 2 &line 1 &changed line 4\\
+line 3 &line 3 &changed line 2 &@y\\
+line 4 &@y &changed line 3 &final line 4\\
+line 5 &changed line 2 &inserted line &@z\\
+@i ctie.inc &changed line 3 &line 4\\
+line 6 &inserted line &@y &@x\\
+line 7 &@z &final line 2 &changed inc line 1\\
+line 8 & &final line 3 &inserted inc line\\
+line 9 &@x &changed line 4 &@y\\
+line 10 &line 7 &@z &final inc line 1\\
+\eof &@y & &@i "ctie.inc2"\\
+ &changed line 7 &@x &@z\\
+ &@z &inc line 1 &\eof\\
+ &\eof &@y\\
+ & &changed inc line 1\\
+ & &inserted inc line\\
+ & &@z\\
+ & &\\
+ & &@x\\
+ & &changed line 7\\
+ & &line 8\\
+ & &@y\\
+ & &final line 7\\
+ & &final line 8\\
+ & &@z\\
+ & &\eof\\
+\end{tabular}
+\end{center}
+
+The included files are as follows:
+
+\begin{center}
+\ttfamily
+\begin{tabular}{lll}
+\multicolumn1{c}{\textbf{\textrm{ctie.inc}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.inc1}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.inc2}}}\\[1pt]
+\hline
+inc line 1 &included inc line &final inserted inc line\\
+inc line 2 &\eof &\eof\\
+@i ctie.inc1\\
+inc line 3\\
+\eof\\
+\end{tabular}
+\end{center}
+
+\clearpage
+
+Using these input files and running \.{CTIE} with the following
+commands to create a new master file and a new change file will result
+in the following output files.
+
+\begin{tabbing}
+ \quad For the master file:\qquad\=\texttt{ctie -m ctie.outm ctie.cf1
+ ctie.cf2 ctie.cf3}\\
+ \quad For the change file:\>\texttt{ctie -c ctie.outc ctie.cf1
+ ctie.cf2 ctie.cf3}
+\end{tabbing}
+
+\begin{center}
+\ttfamily
+\begin{tabular}{ll}
+\multicolumn1{c}{\textbf{\textrm{ctie.outm}}}&
+ \multicolumn1{c}{\textbf{\textrm{ctie.outc}}}\\[1pt]
+\hline
+final line 2 &@x\\
+final line 3 &line 1\\
+final line 4 &line 2\\
+line 5 &line 3\\
+final inc line 1 &line 4\\
+final inserted inc line &@y\\
+inc line 2 &final line 2\\
+included inc line &final line 3\\
+inc line 3 &final line 4\\
+line 6 &@z\\
+final line 7 &\\
+final line 8 &@x\\
+line 9 &inc line 1\\
+line 10 &@y\\
+ &final inc line 1\\
+ &final inserted inc line\\
+ &@z\\
+ &\\
+ &@x\\
+ &line 7\\
+ &line 8\\
+ &@y\\
+ &final line 7\\
+ &final line 8\\
+ &@z\\
+\end{tabular}
+\end{center}
+
+
+\end{document}