summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/tiedir
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/tiedir
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/tiedir')
-rw-r--r--Build/source/texk/web2c/tiedir/MANIFEST21
-rw-r--r--Build/source/texk/web2c/tiedir/Makefile.cweb38
-rw-r--r--Build/source/texk/web2c/tiedir/README58
-rw-r--r--Build/source/texk/web2c/tiedir/tie-w2c.ch109
-rw-r--r--Build/source/texk/web2c/tiedir/tie.139
-rw-r--r--Build/source/texk/web2c/tiedir/tie.1.dvibin0 -> 1804 bytes
-rw-r--r--Build/source/texk/web2c/tiedir/tie.1.nroffed66
-rw-r--r--Build/source/texk/web2c/tiedir/tie.c920
-rw-r--r--Build/source/texk/web2c/tiedir/tie.cf114
-rw-r--r--Build/source/texk/web2c/tiedir/tie.cf219
-rw-r--r--Build/source/texk/web2c/tiedir/tie.cf35
-rw-r--r--Build/source/texk/web2c/tiedir/tie.chf.gen19
-rw-r--r--Build/source/texk/web2c/tiedir/tie.master.gen14
-rw-r--r--Build/source/texk/web2c/tiedir/tie.rc34
-rw-r--r--Build/source/texk/web2c/tiedir/tie.tie15
-rw-r--r--Build/source/texk/web2c/tiedir/tie.w1297
-rw-r--r--Build/source/texk/web2c/tiedir/tiedoc.tex176
17 files changed, 2844 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/tiedir/MANIFEST b/Build/source/texk/web2c/tiedir/MANIFEST
new file mode 100644
index 00000000000..b2dc9ed29cc
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/MANIFEST
@@ -0,0 +1,21 @@
+README guess what, but read it before proceeding
+MANIFEST this list of files
+
+Makefile.cweb UN*X Makefile to create tie from the sources
+ (requires a working ctangle processor for source changes)
+tie.w the source of tie, written in CWEB
+tie.c a pretangled version of tie.w
+
+tie.tie a small test suite (master)
+tie.cf1 with several change files
+tie.cf2
+tie.cf3
+tie.chf.gen the supposed to be generated merged change file
+tie.master.gen the supposed to be generated new master file
+
+tiedoc.tex a short introduction on tie (LaTeX source)
+
+tie.1 a UN*X style man page for tie
+tie.1.dvi a `groff'ed version on man page tie.1
+tie.1.nroffed an `nroff'ed version of man page tie.1, backspaces
+ for underlining or overstriking removed
diff --git a/Build/source/texk/web2c/tiedir/Makefile.cweb b/Build/source/texk/web2c/tiedir/Makefile.cweb
new file mode 100644
index 00000000000..09320188459
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/Makefile.cweb
@@ -0,0 +1,38 @@
+#
+# Makefile for tie distribution - 21 Dec 92
+#
+# This file makes TIE and needs ctangle from cweb distribution.
+# Try `touch tie.c' first, if you don't have ctangle.
+#
+
+CTANGLE=ctangle
+BINDIR=.
+TIE=$(BINDIR)/tie
+
+CFLAGS=
+LDFLAGS=-s
+
+default: tie
+
+
+# TIE
+tie.o: tie.c
+
+tie: tie.o
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $(TIE) tie.o
+
+tie.c: tie.w
+ $(CTANGLE) tie
+
+
+clean:
+ rm -f tie.o tie.outc tie.outm tie.tex tie.log tie.toc tiedoc.log
+
+veryclean: clean
+ rm -f $(BINDIR)/tie tie.dvi tiedoc.dvi tiedoc.aux
+
+ttest: $(TIE)
+ $(TIE) -c tie.outc tie.tie tie.cf?
+ diff tie.outc tie.chf.gen
+ $(TIE) -m tie.outm tie.tie tie.cf?
+ diff tie.outm tie.master.gen
diff --git a/Build/source/texk/web2c/tiedir/README b/Build/source/texk/web2c/tiedir/README
new file mode 100644
index 00000000000..1b3bb7be0de
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/README
@@ -0,0 +1,58 @@
+This is the README file of the `tie' distribution.
+ The current version is 2.4.
+ This file was created on 18 Dec 92.
+ This file was updated on 15 Jul 93.
+
+
+SUBJECT:
+
+`Tie' is a program which was first developed to allow WEB programmers
+(be it Pascal-, C- or any other WEB) to add more than one change file
+to their programs.
+
+ But it can be used to create new versions of the WEB file with
+incorporated changes as well. This feature does not depend 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).
+ This makes `tie' also usable for any other language, or even data
+files. See the documentation tiedoc.tex and the example file tie.tie.
+
+ Actually, this gives a second file update mechanism besides `patch'.
+Whereas patch relies on line numbers and/or precise contexts produced
+by diff, tie depends on the order of changes and on a an amount of
+context lines determined manually.
+
+
+REQUIREMENTS:
+
+This version of `tie' is written in CWEB. To preprocess and compile
+the source you will need a working `ctangle'.
+ A pretangled tie.c is supplied which has been compiled successfully
+on a variety of workstations using either the manufacturer supplied
+C compiler in the K&R or ANSI version, or gcc (version 1.40).
+ Please note, that the CWEB by Silvio Levy and Donald E. Knuth must
+be at least at version 2.8, to process and compile `tie' without
+problems.
+
+
+DISTRIBUTION:
+
+The reference version of tie may be retrieved by anonymous ftp from
+
+ ftp.th-darmstadt.de [130.83.55.75]
+ directory pub/programming/literate-programming/Tools
+ file tie-<version>.tar.Z
+
+where <version> is the most current version number.
+ See the source file tie.w for details of the distribution policy.
+
+
+BUGS/ENHANCEMENTS:
+
+If you detect bugs in the implementation of `tie' or have
+suggestions to enhance functionality or improve portability,
+please send a message to
+
+ Klaus Guntermann <guntermann@iti.informatik.th-darmstadt.de>
+
diff --git a/Build/source/texk/web2c/tiedir/tie-w2c.ch b/Build/source/texk/web2c/tiedir/tie-w2c.ch
new file mode 100644
index 00000000000..6dfa043b38b
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie-w2c.ch
@@ -0,0 +1,109 @@
+% Changes to adapt tie to web2c.
+% Copyright 2001 by Olaf Weber
+% This file is in the Public Domain.
+
+@x Already in cpascal.h.
+@d incr(v) v+=1 /* increase a variable by unity */
+@d decr(v) v-=1 /* decrease a variable by unity */
+@y
+@z
+
+@x
+@ Furthermore we include the additional types |boolean| and |string|.
+@d false 0
+@d true 1
+@<Global types@>=
+typedef int boolean;
+typedef char* string;
+@y
+@ Furthermore we include the additional types |boolean| and |string|.
+/* boolean, false, true; string; all from cpascal.h */
+@z
+
+@x -- we need more input files.
+#define max_file_index 9
+/* we don't think that anyone needs more than 9 change files,
+@y
+#define max_file_index 32
+/* we don't think that anyone needs more than 32 change files,
+@z
+
+@x -- add to global includes.
+#include <stdio.h>
+@y
+#include "cpascal.h"
+#include <stdio.h>
+/* Also redefine usage to avoid clash with function from lib. */
+#define usage tieusage
+@z
+
+@x
+void get_line(i)
+ file_index i;
+@y
+void get_line P1C(file_index, i)
+@z
+
+@x
+void err_loc(i) /* prints location of error */
+ int i;
+@y
+void err_loc P1C(int, i) /* prints location of error */
+@z
+
+@x
+boolean lines_dont_match(i,j)
+ file_index i,j;
+@y
+boolean lines_dont_match P2C(file_index, i, file_index, j)
+@z
+
+@x
+void init_change_file(i,b)
+ file_index i; boolean b;
+@y
+void init_change_file P2C(file_index, i, boolean, b)
+@z
+
+@x
+void put_line(j)
+ file_index j;
+@y
+void put_line P1C(file_index, j)
+@z
+
+@x
+boolean e_of_ch_module(i)
+ file_index i;
+@y
+boolean e_of_ch_module P1C(file_index, i)
+@z
+
+@x
+boolean e_of_ch_preamble(i)
+ file_index i;
+@y
+boolean e_of_ch_preamble P1C(file_index, i)
+@z
+
+@x
+void usage()
+@y
+void usage P1H(void)
+@z
+
+@x
+main(argc,argv)
+ int argc; string *argv;
+@y
+int main P2C(int, argc, string *, argv)
+@z
+
+@x
+ print_ln(banner); /* print a ``banner line'' */
+ print_ln(copyright); /* include the copyright notice */
+@y
+ print(banner); /* print a ``banner line'' */
+ print_ln(versionstring); /* Web2C version */
+ print_ln(copyright); /* include the copyright notice */
+@z
diff --git a/Build/source/texk/web2c/tiedir/tie.1 b/Build/source/texk/web2c/tiedir/tie.1
new file mode 100644
index 00000000000..13d132d8ed6
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.1
@@ -0,0 +1,39 @@
+.TH TIE 1L 9/24/92
+.SH NAME
+tie \- merge or apply WEB change files
+.SH SYNOPSIS
+.B tie
+.B \-c|\-m
+.I outputfile masterfile changefile...
+
+.SH DESCRIPTION
+The
+.I tie
+program is used to process multiple change files used with the WEB
+system for literate programming. The WEB programs allow to apply
+patches to a source file (the
+.IR masterfile )
+by means of a number of change files (often only a single change file
+is allowed).
+.I Tie
+can be used to either merge up to nine change files into a single one
+or to apply the changes to the
+.I masterfile
+in order to create a new one. Output of either the new change file or
+the patched master file goes into
+.I outputfile.
+.SS OPTIONS
+.TP
+.B \-c
+Create a single change file from the given
+.I changefiles.
+.TP
+.B \-m
+Create a new master file by applying the given
+.I changefiles.
+.SH "SEE ALSO"
+.br
+web(1), cweb(1l).
+.SH "AUTHOR"
+Klaus Guntermann, TH Darmstadt, Institut f. Theoretische Informatik. Man page
+by Joachim Schnitter, TH Darmstadt, Phys. Chemie I.
diff --git a/Build/source/texk/web2c/tiedir/tie.1.dvi b/Build/source/texk/web2c/tiedir/tie.1.dvi
new file mode 100644
index 00000000000..75beacafbc8
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.1.dvi
Binary files differ
diff --git a/Build/source/texk/web2c/tiedir/tie.1.nroffed b/Build/source/texk/web2c/tiedir/tie.1.nroffed
new file mode 100644
index 00000000000..3701bd617ba
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.1.nroffed
@@ -0,0 +1,66 @@
+
+
+
+ TIE(1L) (9/24/92) TIE(1L)
+
+
+
+ NAME
+ tie - merge or apply WEB change files
+
+ SYNOPSIS
+ tie -c|-m outputfile masterfile changefile1 [ ...
+ changefile9 ]
+
+
+ DESCRIPTION
+ The tie program is used to process multiple change files
+ used with the WEB system for literate programming. The
+ WEB programs allow to apply patches to a source file (the
+ masterfile) by means of a number of change files (often
+ only a single change file is allowed). Tie can be used to
+ either merge up to nine change files into a single one or to
+ apply the changes to the masterfile in order to create a new
+ one. Output of either the new change file or the patched
+ master file goes into outputfile.
+
+ OPTIONS
+ -c Create a single change file from the given masterfile.
+
+ -m Create a new master file by applying the given
+ changefiles.
+
+ SEE ALSO
+ web(1), cweb(1l).
+
+ AUTHOR
+ Klaus Guntermann, TH Darmstadt, Institut f. Theoretische
+ Informatik. Man page by Joachim Schnitter, TH Darmstadt,
+ Phys. Chemie I.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Page 1 (printed 12/17/92)
+
+
+
diff --git a/Build/source/texk/web2c/tiedir/tie.c b/Build/source/texk/web2c/tiedir/tie.c
new file mode 100644
index 00000000000..ccf39c03c63
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.c
@@ -0,0 +1,920 @@
+#define banner "This is TIE, CWEB Version 2.4."
+#define copyright \
+"Copyright (c) 1989,1992 by THD/ITI. All rights reserved." \
+ \
+
+#define incr(v)v+= 1
+#define decr(v)v-= 1
+#define loop while(1)
+#define do_nothing
+#define false 0
+#define true 1
+#define spotless 0
+#define troublesome 1
+#define fatal 2 \
+
+#define first_text_char 0
+#define last_text_char 255 \
+
+#define map_xchr(c)(text_char)(c) \
+
+#define map_xord(c)(ASCII_Code)(c) \
+ \
+
+#define tab_mark 9
+#define nl_mark 10
+#define form_feed 12 \
+ \
+
+#define term_out stdout
+#define print(a)fprintf(term_out,a)
+#define print2(a,b)fprintf(term_out,a,b)
+#define print3(a,b,c)fprintf(term_out,a,b,c)
+#define print_c(v)fputc(v,term_out);
+#define new_line(v)fputc('\n',v)
+#define term_new_line new_line(term_out) \
+
+#define print_ln(v){fprintf(term_out,v);term_new_line;} \
+
+#define print2_ln(a,b){print2(a,b);term_new_line;}
+#define print3_ln(a,b,c){print3(a,b,c);term_new_line;} \
+
+#define print_nl(v){term_new_line;print(v);} \
+
+#define print2_nl(a,b){term_new_line;print2(a,b);} \
+ \
+
+#define update_terminal fflush(term_out) \
+ \
+ \
+ \
+ \
+
+#define error_loc(m)err_loc(m);history= troublesome;}
+#define err_print(m){print_nl(m);error_loc \
+
+#define fatal_error(m){ \
+print(m);print_c('.');history= fatal; \
+term_new_line;jump_out(); \
+} \
+ \
+
+#define jump_out()exit(1) \
+ \
+ \
+ \
+ \
+
+#define none (max_file_index+1) \
+
+/*2:*/
+#line 112 "tie.w"
+
+/*15:*/
+#line 478 "tie.w"
+
+#include <stdio.h>
+
+
+/*:15*//*16:*/
+#line 486 "tie.w"
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+/*:16*/
+#line 113 "tie.w"
+
+/*5:*/
+#line 142 "tie.w"
+
+#define buf_size 512
+#define max_file_index 9
+
+
+
+
+/*:5*/
+#line 114 "tie.w"
+
+/*4:*/
+#line 133 "tie.w"
+
+typedef int boolean;
+typedef char*string;
+
+
+/*:4*//*7:*/
+#line 224 "tie.w"
+
+#define max_ASCII (126+1)
+typedef unsigned char ASCII_Code;
+
+
+
+/*:7*//*8:*/
+#line 250 "tie.w"
+
+typedef unsigned char text_char;
+typedef FILE*text_file;
+
+
+/*:8*//*18:*/
+#line 529 "tie.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;
+
+
+/*:18*//*19:*/
+#line 547 "tie.w"
+
+#define normal 0
+#define pre 1
+#define post 2
+typedef int out_md_type;
+
+
+/*:19*//*20:*/
+#line 557 "tie.w"
+
+typedef int buffer_index;
+typedef int file_index;
+
+
+/*:20*//*21:*/
+#line 566 "tie.w"
+
+typedef struct _idsc{
+string name_of_file;
+ASCII_Code buffer[buf_size];
+in_file_modes mode;
+long line;
+file_types type_of_file;
+buffer_index limit;
+text_file the_file;
+}input_description;
+
+
+/*:21*/
+#line 115 "tie.w"
+
+/*6:*/
+#line 159 "tie.w"
+
+static int history= spotless;
+
+
+
+/*:6*//*9:*/
+#line 270 "tie.w"
+
+static ASCII_Code xord[last_text_char+1];
+
+static text_char xchr[max_ASCII+1];
+
+
+
+/*:9*//*22:*/
+#line 582 "tie.w"
+
+static file_index actual_input,test_input,no_ch;
+static file_types prod_chf= unknown;
+static out_md_type out_mode;
+
+
+/*:22*//*23:*/
+#line 594 "tie.w"
+
+static input_description*input_organization[max_file_index+1];
+
+
+
+
+
+/*:23*//*26:*/
+#line 641 "tie.w"
+
+static boolean input_has_ended= false;
+
+
+/*:26*//*35:*/
+#line 801 "tie.w"
+
+static text_file out_file;
+static string out_name;
+
+
+/*:35*/
+#line 116 "tie.w"
+
+/*31:*/
+#line 744 "tie.w"
+
+void err_loc(i)
+int i;
+{
+print3_ln(" (file %s, l.%ld).",
+input_organization[i]->name_of_file,
+input_organization[i]->line);
+}
+
+
+/*:31*/
+#line 117 "tie.w"
+
+/*24:*/
+#line 616 "tie.w"
+
+void get_line(i)
+file_index i;
+{register input_description*inp_desc= input_organization[i];
+if(inp_desc->mode==ignore)return;
+if(feof(inp_desc->the_file))
+/*25:*/
+#line 630 "tie.w"
+
+{
+inp_desc->mode= ignore;
+inp_desc->limit= -1;
+if(inp_desc->type_of_file==master)input_has_ended= true;
+return;
+}
+
+
+/*:25*/
+#line 622 "tie.w"
+
+/*27:*/
+#line 655 "tie.w"
+
+{int final_limit;
+int c;
+/*28:*/
+#line 679 "tie.w"
+
+incr(inp_desc->line);
+if(inp_desc->type_of_file==master&&inp_desc->line%100==0){
+if(inp_desc->line%500==0)print2("%ld",inp_desc->line);
+else print_c('.');
+update_terminal;
+}
+
+
+/*:28*/
+#line 659 "tie.w"
+
+inp_desc->limit= final_limit= 0;
+while(inp_desc->limit<buf_size){
+c= fgetc(inp_desc->the_file);
+/*29:*/
+#line 696 "tie.w"
+
+if(c==EOF){
+if(inp_desc->limit<=0){
+inp_desc->mode= ignore;
+inp_desc->limit= -1;
+if(inp_desc->type_of_file==master)input_has_ended= true;
+return;
+}else{
+c= nl_mark;
+break;
+}
+}
+
+
+/*:29*/
+#line 664 "tie.w"
+
+inp_desc->buffer[inp_desc->limit++]= c= map_xord(c);
+if(c==nl_mark)break;
+if(c!=32&&c!=tab_mark)
+final_limit= inp_desc->limit;
+}
+/*30:*/
+#line 712 "tie.w"
+
+if(c!=nl_mark){
+err_print("! Input line too long")(i);
+
+while((c= fgetc(inp_desc->the_file))!=EOF&&map_xord(c)!=nl_mark)
+do_nothing;
+}
+
+
+
+
+
+/*:30*/
+#line 670 "tie.w"
+
+inp_desc->limit= final_limit;
+}
+
+
+/*:27*/
+#line 623 "tie.w"
+
+}
+
+
+/*:24*//*38:*/
+#line 850 "tie.w"
+
+boolean lines_dont_match(i,j)
+file_index i,j;
+{
+buffer_index k,lmt;
+if(input_organization[i]->limit!=input_organization[j]->limit)
+return(true);
+lmt= input_organization[i]->limit;
+for(k= 0;k<lmt;k++)
+if(input_organization[i]->buffer[k]!=input_organization[j]->buffer[k])
+return(true);
+return(false);
+}
+
+
+/*:38*//*39:*/
+#line 871 "tie.w"
+
+void init_change_file(i,b)
+file_index i;boolean b;
+{register input_description*inp_desc= input_organization[i];
+/*40:*/
+#line 885 "tie.w"
+
+loop{ASCII_Code c;
+get_line(i);
+if(inp_desc->mode==ignore)return;
+if(inp_desc->limit<2)continue;
+if(inp_desc->buffer[0]!=64)continue;
+c= inp_desc->buffer[1];
+if(c>=88&&c<=90)
+c+= 122-90;
+if(c==120)break;
+if(c==121||c==122)
+if(b)
+err_print("! Where is the matching @x?")(i);
+
+}
+
+
+/*:40*/
+#line 875 "tie.w"
+
+/*41:*/
+#line 904 "tie.w"
+
+do{
+get_line(i);
+if(inp_desc->mode==ignore){
+err_print("! Change file ended after @x")(i);
+
+return;
+}
+}while(inp_desc->limit<=0);
+
+
+/*:41*/
+#line 876 "tie.w"
+
+}
+
+
+/*:39*//*42:*/
+#line 918 "tie.w"
+
+void put_line(j)
+file_index j;
+{buffer_index i;
+buffer_index lmt;
+ASCII_Code*p;
+lmt= input_organization[j]->limit;
+p= input_organization[j]->buffer;
+for(i= 0;i<lmt;i++)fputc(map_xchr(*p++),out_file);
+new_line(out_file);
+}
+
+
+/*:42*//*43:*/
+#line 934 "tie.w"
+
+boolean e_of_ch_module(i)
+file_index i;
+{register input_description*inp_desc= input_organization[i];
+if(inp_desc->limit<0){
+print_nl("! At the end of change file missing @z ");
+
+print2("%s",input_organization[i]->name_of_file);
+term_new_line;
+return(true);
+}else if(inp_desc->limit>=2)if(inp_desc->buffer[0]==64&&
+(inp_desc->buffer[1]==90||inp_desc->buffer[1]==122))
+return(true);
+return(false);
+}
+
+
+/*:43*//*44:*/
+#line 954 "tie.w"
+
+boolean e_of_ch_preamble(i)
+file_index i;
+{register input_description*inp_desc= input_organization[i];
+if(inp_desc->limit>=2&&inp_desc->buffer[0]==64)
+if(inp_desc->buffer[1]==89||inp_desc->buffer[1]==121)return(true);
+return(false);
+}
+
+
+
+/*:44*//*55:*/
+#line 1157 "tie.w"
+
+void usage()
+{
+print("Usage: tie -[mc] outfile master changefile(s)");
+term_new_line;
+jump_out();
+}
+
+
+/*:55*/
+#line 118 "tie.w"
+
+/*59:*/
+#line 1235 "tie.w"
+
+main(argc,argv)
+int argc;string*argv;
+{{/*12:*/
+#line 408 "tie.w"
+
+int i;
+
+
+/*:12*/
+#line 1238 "tie.w"
+
+/*10:*/
+#line 296 "tie.w"
+
+xchr[32]= ' ';
+xchr[33]= '!';
+xchr[34]= '\"';
+xchr[35]= '#';
+xchr[36]= '$';
+xchr[37]= '%';
+xchr[38]= '&';
+xchr[39]= '\'';
+xchr[40]= '(';
+xchr[41]= ')';
+xchr[42]= '*';
+xchr[43]= '+';
+xchr[44]= ',';
+xchr[45]= '-';
+xchr[46]= '.';
+xchr[47]= '/';
+xchr[48]= '0';
+xchr[49]= '1';
+xchr[50]= '2';
+xchr[51]= '3';
+xchr[52]= '4';
+xchr[53]= '5';
+xchr[54]= '6';
+xchr[55]= '7';
+xchr[56]= '8';
+xchr[57]= '9';
+xchr[58]= ':';
+xchr[59]= ';';
+xchr[60]= '<';
+xchr[61]= '=';
+xchr[62]= '>';
+xchr[63]= '?';
+xchr[64]= '@';
+xchr[65]= 'A';
+xchr[66]= 'B';
+xchr[67]= 'C';
+xchr[68]= 'D';
+xchr[69]= 'E';
+xchr[70]= 'F';
+xchr[71]= 'G';
+xchr[72]= 'H';
+xchr[73]= 'I';
+xchr[74]= 'J';
+xchr[75]= 'K';
+xchr[76]= 'L';
+xchr[77]= 'M';
+xchr[78]= 'N';
+xchr[79]= 'O';
+xchr[80]= 'P';
+xchr[81]= 'Q';
+xchr[82]= 'R';
+xchr[83]= 'S';
+xchr[84]= 'T';
+xchr[85]= 'U';
+xchr[86]= 'V';
+xchr[87]= 'W';
+xchr[88]= 'X';
+xchr[89]= 'Y';
+xchr[90]= 'Z';
+xchr[91]= '[';
+xchr[92]= '\\';
+xchr[93]= ']';
+xchr[94]= '^';
+xchr[95]= '_';
+xchr[96]= '`';
+xchr[97]= 'a';
+xchr[98]= 'b';
+xchr[99]= 'c';
+xchr[100]= 'd';
+xchr[101]= 'e';
+xchr[102]= 'f';
+xchr[103]= 'g';
+xchr[104]= 'h';
+xchr[105]= 'i';
+xchr[106]= 'j';
+xchr[107]= 'k';
+xchr[108]= 'l';
+xchr[109]= 'm';
+xchr[110]= 'n';
+xchr[111]= 'o';
+xchr[112]= 'p';
+xchr[113]= 'q';
+xchr[114]= 'r';
+xchr[115]= 's';
+xchr[116]= 't';
+xchr[117]= 'u';
+xchr[118]= 'v';
+xchr[119]= 'w';
+xchr[120]= 'x';
+xchr[121]= 'y';
+xchr[122]= 'z';
+xchr[123]= '{';
+xchr[124]= '|';
+xchr[125]= '}';
+xchr[126]= '~';
+xchr[0]= ' ';xchr[0x7F]= ' ';
+
+
+/*:10*//*13:*/
+#line 429 "tie.w"
+
+for(i= 1;i<32;xchr[i++]= ' ');
+xchr[tab_mark]= '\t';
+xchr[form_feed]= '\f';
+xchr[nl_mark]= '\n';
+
+
+/*:13*//*14:*/
+#line 440 "tie.w"
+
+for(i= first_text_char;i<=last_text_char;xord[i++]= 32)do_nothing;
+for(i= 1;i<=126;i++)xord[xchr[i]]= i;
+
+
+
+
+
+/*:14*/
+#line 1239 "tie.w"
+
+}
+print_ln(banner);
+print_ln(copyright);
+actual_input= 0;
+out_mode= normal;
+/*56:*/
+#line 1177 "tie.w"
+
+{int act_arg;
+if(argc<5||argc>max_file_index+4-1)usage();
+no_ch= -1;
+for(act_arg= 1;act_arg<argc;act_arg++){
+if(argv[act_arg][0]=='-')/*57:*/
+#line 1195 "tie.w"
+
+if(prod_chf!=unknown)usage();
+else
+switch(argv[act_arg][1]){
+case'c':
+case'C':prod_chf= chf;break;
+case'm':
+case'M':prod_chf= master;break;
+default:usage();
+}
+
+
+/*:57*/
+#line 1182 "tie.w"
+
+else/*58:*/
+#line 1211 "tie.w"
+
+{if(no_ch==(-1)){
+out_name= argv[act_arg];
+}else{register input_description*inp_desc;
+inp_desc= (input_description*)
+malloc(sizeof(input_description));
+if(inp_desc==NULL)
+fatal_error("! No memory for descriptor");
+
+inp_desc->mode= search;
+inp_desc->line= 0;
+inp_desc->type_of_file= chf;
+inp_desc->limit= 0;
+inp_desc->name_of_file= argv[act_arg];
+input_organization[no_ch]= inp_desc;
+}
+incr(no_ch);
+}
+
+
+/*:58*/
+#line 1183 "tie.w"
+
+}
+if(no_ch<=0||prod_chf==unknown)usage();
+}
+
+
+/*:56*/
+#line 1245 "tie.w"
+
+/*34:*/
+#line 788 "tie.w"
+
+{
+out_file= fopen(out_name,"w");
+if(out_file==NULL){
+fatal_error("! Could not open/create output file");
+
+}
+}
+
+
+/*:34*/
+#line 1246 "tie.w"
+
+/*36:*/
+#line 809 "tie.w"
+
+{input_organization[0]->the_file=
+fopen(input_organization[0]->name_of_file,"r");
+if(input_organization[0]->the_file==NULL)
+fatal_error("! Could not open master file");
+
+print2("(%s)",input_organization[0]->name_of_file);
+term_new_line;
+input_organization[0]->type_of_file= master;
+get_line(0);
+}
+
+/*:36*/
+#line 1247 "tie.w"
+
+/*37:*/
+#line 825 "tie.w"
+
+{file_index i;
+i= 1;
+while(i<no_ch){
+input_organization[i]->the_file=
+fopen(input_organization[i]->name_of_file,"r");
+if(input_organization[i]->the_file==NULL)
+fatal_error("!Could not open change file");
+
+print2("(%s)",input_organization[i]->name_of_file);
+term_new_line;
+init_change_file(i,true);
+incr(i);
+}
+}
+
+
+
+
+
+/*:37*/
+#line 1248 "tie.w"
+
+/*53:*/
+#line 1128 "tie.w"
+
+actual_input= 0;
+input_has_ended= false;
+while(input_has_ended==false||actual_input!=0)
+/*45:*/
+#line 970 "tie.w"
+
+{file_index test_file;
+/*46:*/
+#line 985 "tie.w"
+
+{register input_description*inp_desc;
+while(actual_input>0&&e_of_ch_module(actual_input)){
+inp_desc= input_organization[actual_input];
+if(inp_desc->type_of_file==master){
+
+fatal_error("! This can't happen: change file is master file");
+
+}
+inp_desc->mode= search;
+init_change_file(actual_input,true);
+while((input_organization[actual_input]->mode!=reading
+&&actual_input>0))decr(actual_input);
+}
+}
+
+
+/*:46*/
+#line 972 "tie.w"
+
+if(input_has_ended&&actual_input==0)break;
+/*47:*/
+#line 1009 "tie.w"
+
+test_input= none;
+test_file= actual_input;
+while(test_input==none&&test_file<no_ch-1){
+incr(test_file);
+switch(input_organization[test_file]->mode){
+case search:if(lines_dont_match(actual_input,test_file)==false){
+input_organization[test_file]->mode= test;
+test_input= test_file;
+}
+break;
+case test:if(lines_dont_match(actual_input,test_file)==true){
+
+input_organization[test_file]->mode= search;
+err_print("! Sections do not match")(actual_input);
+
+err_loc(test_file);
+init_change_file(test_file,false);
+}else test_input= test_file;
+break;
+case reading:do_nothing;
+break;
+case ignore:do_nothing;
+break;
+}
+}
+
+
+/*:47*/
+#line 974 "tie.w"
+
+/*48:*/
+#line 1043 "tie.w"
+
+if(prod_chf==chf){
+loop{
+/*49:*/
+#line 1057 "tie.w"
+
+if(out_mode==normal){
+if(test_input!=none){
+fputc(map_xchr(64),out_file);fputc(map_xchr(120),out_file);
+new_line(out_file);
+out_mode= pre;
+}else break;
+}
+
+
+/*:49*/
+#line 1046 "tie.w"
+
+/*50:*/
+#line 1071 "tie.w"
+
+
+if(out_mode==pre){
+if(test_input==none){
+fputc(map_xchr(64),out_file);fputc(map_xchr(121),out_file);
+new_line(out_file);
+out_mode= post;
+}else{
+if(input_organization[actual_input]->type_of_file==master)
+put_line(actual_input);
+break;
+}
+}
+
+
+/*:50*/
+#line 1047 "tie.w"
+
+/*51:*/
+#line 1092 "tie.w"
+
+if(out_mode==post){
+if(input_organization[actual_input]->type_of_file==chf){
+if(test_input==none)put_line(actual_input);
+break;
+}else{
+fputc(map_xchr(64),out_file);fputc(map_xchr(122),out_file);
+new_line(out_file);
+new_line(out_file);
+out_mode= normal;
+}
+}
+
+
+/*:51*/
+#line 1048 "tie.w"
+
+}
+}else
+if(test_input==none)put_line(actual_input);
+
+
+/*:48*/
+#line 975 "tie.w"
+
+/*52:*/
+#line 1109 "tie.w"
+
+get_line(actual_input);
+if(test_input!=none){
+get_line(test_input);
+if(e_of_ch_preamble(test_input)==true){
+get_line(test_input);
+input_organization[test_input]->mode= reading;
+actual_input= test_input;
+test_input= none;
+}
+}
+
+
+/*:52*/
+#line 976 "tie.w"
+
+}
+
+
+/*:45*/
+#line 1132 "tie.w"
+
+if(out_mode==post){
+fputc(map_xchr(64),out_file);fputc(map_xchr(122),out_file);
+new_line(out_file);
+}
+
+
+/*:53*/
+#line 1249 "tie.w"
+
+/*54:*/
+#line 1143 "tie.w"
+
+{file_index i;
+for(i= 1;i<no_ch;i++){
+if(input_organization[i]->mode!=ignore)
+err_print("! Change file entry did not match")(i);
+
+}
+}
+
+
+/*:54*/
+#line 1250 "tie.w"
+
+/*60:*/
+#line 1261 "tie.w"
+
+{string msg;
+switch(history){
+case spotless:msg= "No errors were found";break;
+case troublesome:msg= "Pardon me, but I think I spotted something wrong.";
+break;
+case fatal:msg= "That was a fatal error, my friend";break;
+}
+print2_nl("(%s.)",msg);term_new_line;
+exit(history==spotless?0:1);
+}
+
+
+
+
+
+/*:60*/
+#line 1251 "tie.w"
+
+}
+
+/*:59*/
+#line 119 "tie.w"
+
+
+/*:2*/
diff --git a/Build/source/texk/web2c/tiedir/tie.cf1 b/Build/source/texk/web2c/tiedir/tie.cf1
new file mode 100644
index 00000000000..5b1165435c9
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.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/tiedir/tie.cf2 b/Build/source/texk/web2c/tiedir/tie.cf2
new file mode 100644
index 00000000000..386bc375876
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.cf2
@@ -0,0 +1,19 @@
+@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
+changed line 7
+line 8
+@y
+final line 7
+final line 8
+@z
diff --git a/Build/source/texk/web2c/tiedir/tie.cf3 b/Build/source/texk/web2c/tiedir/tie.cf3
new file mode 100644
index 00000000000..6c0e2458daf
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.cf3
@@ -0,0 +1,5 @@
+@x
+changed line 4
+@y
+final line 4
+@z
diff --git a/Build/source/texk/web2c/tiedir/tie.chf.gen b/Build/source/texk/web2c/tiedir/tie.chf.gen
new file mode 100644
index 00000000000..f0b0130957a
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.chf.gen
@@ -0,0 +1,19 @@
+@x
+line 1
+line 2
+line 3
+line 4
+@y
+final line 2
+final line 3
+final line 4
+@z
+
+@x
+line 7
+line 8
+@y
+final line 7
+final line 8
+@z
+
diff --git a/Build/source/texk/web2c/tiedir/tie.master.gen b/Build/source/texk/web2c/tiedir/tie.master.gen
new file mode 100644
index 00000000000..e25e93b82d9
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.master.gen
@@ -0,0 +1,14 @@
+final line 2
+final line 3
+final line 4
+line 5
+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/tiedir/tie.rc b/Build/source/texk/web2c/tiedir/tie.rc
new file mode 100644
index 00000000000..6c5830d4cd4
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.rc
@@ -0,0 +1,34 @@
+/* tie.rc: tie resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " tie 2.4"
+
+#define VER_INTERNALNAME_STR "tie"
+#define VER_ORIGINALFILENAME_STR "tie.exe"
+
+#define VER_FILEDESCRIPTION_STR "Merges change files to master web file"
+
+#define VER_LEGALCOPYRIGHT_STR " Copyright (c) 1989,1992 by THD/ITI."
+
+#include <texlive.version>
+
+/* tie.rc ends here */
diff --git a/Build/source/texk/web2c/tiedir/tie.tie b/Build/source/texk/web2c/tiedir/tie.tie
new file mode 100644
index 00000000000..59c1d4c0a23
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.tie
@@ -0,0 +1,15 @@
+line 1
+line 2
+line 3
+line 4
+line 5
+line 6
+line 7
+line 8
+line 9
+line 10
+The character set:
+abcdefghijklmnopqrstuvwxyz
+ABCDEFGHIJKLMNOPQRSTUVWXYZ
+=!"#$%&/()?'`^~|-+[]{}@\;:
+ 0123456789<>.,*_
diff --git a/Build/source/texk/web2c/tiedir/tie.w b/Build/source/texk/web2c/tiedir/tie.w
new file mode 100644
index 00000000000..5aa6abf87d1
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tie.w
@@ -0,0 +1,1297 @@
+% This is TIE.W as of 17 Dec 92
+%---------------------------------------------------------
+% Copyright (c) 1989,1992 by THD/ITI.
+% 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.
+%
+%
+% Version 1.7 was built alike TIE.WEB Version 1.6 (89-01-27)
+% but used a command line interface only
+% Version 2.0 was revised to include optional tab expansion (89-02-01)
+% Version 2.1 deleted WEB relicts. (-js) (89-10-25)
+% Version 2.2 repaired replacing strategy (89-11-27)
+% Version 2.3 was slightly modified to be processed with the
+% cweb by Levy&Knuth.
+% also repaired loop control for end of changes test (92-09-24)
+% Version 2.4 included <stdlib.h> instead of <malloc.h> when
+% used with ANSI-C (92-12-17)
+%
+
+% Here is TeX material that gets inserted after \input cwebmac
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\mc=cmr9
+\def\PASCAL{Pascal}
+\def\Cl{{\rm C}}
+\def\ASCII{{\mc ASCII}}
+
+\def\title{TIE}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont TIE} processor}
+ \vskip 15pt
+ \centerline{(CWEB Version 2.4)}
+ \vfill}
+\def\botofcontents{
+\null\vfill
+\item{$\copyright$}1989, 1992
+ by Technische Hochschule Darmstadt,\hfill\break
+Fachbereich Informatik, Institut f\"ur Theoretische Informatik\hfill\break
+All rights reserved.\hfill\break
+This program is distributed WITHOUT ANY WARRANTY, express or implied.
+\hfill\break
+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.
+\hfill\break
+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.
+
+\noindent 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. Therefore,
+we introduce the present program to merge a \.{WEB} file and
+several change files producing a new \.{WEB} file. Since
+the input files are tied together, the program is called
+\.{TIE}. Furthermore, the program can 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. The use of \.{TIE} can be
+expanded to other programming languages since this processor
+only knows about the structure of change files and does not
+interpret the master file at all.
+
+The program \.{TIE} has to read lines from several input
+files to bring them in some special ordering. For this
+purpose an algorithm is used which looks a little bit
+complicated. But the method used only needs one buffer line
+for each input file. Thus the storage requirement of
+\.{TIE} does not depend on the input data.
+
+The program is written in \Cl\ and uses only few features of a
+particular environment that may need to be changed in other
+installations.
+E.g.\ it will not use the |enum| type declarations.
+The changes needed may refer to the access of the command line
+if this can be not supported by any \Cl\ compiler.
+
+The ``banner line'' defined here should be changed whenever
+\.{TIE} is modified. This program is put into the public
+domain. Nevertheless the copyright notice must not be
+replaced or modified.
+
+@d banner "This is TIE, CWEB Version 2.4."
+@d copyright
+ "Copyright (c) 1989,1992 by THD/ITI. All rights reserved."
+
+
+@ The main outline of the program is given in the next section.
+This can be used more or less for any \Cl\ program.
+@c
+@<Global |#include|s@>@;
+@<Global constants@>@;
+@<Global types@>@;
+@<Global variables@>@;
+@<Error handling functions@>@;
+@<Internal functions@>@;
+@<The main function@>@;
+
+@ Here are some macros for common programming idioms.
+
+@d incr(v) v+=1 /* increase a variable by unity */
+@d decr(v) v-=1 /* decrease a variable by unity */
+@d loop @+ while (1)@+ /* repeat over and over until a |break| happens */
+@d do_nothing /* empty statement */
+@f loop while
+
+
+@ Furthermore we include the additional types |boolean| and |string|.
+@d false 0
+@d true 1
+@<Global types@>=
+typedef int boolean;
+typedef char* string;
+
+
+@ The following parameters should be sufficient for most
+applications of \.{TIE}.
+@^system dependencies@>
+
+@<Global constants@>=
+#define buf_size 512 /* maximum length of one input line */
+#define max_file_index 9
+/* we don't think that anyone needs more than 9 change files,
+ but \dots\ just change it */
+
+
+@ 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@>=
+static int history=spotless;
+
+
+
+@* The character set.
+
+\noindent One of the main goals in the design of \.{TIE} has
+been to make it readily portable between a wide variety of
+computers. Yet \.{TIE} by its very nature must use a
+greater variety of characters than most computer programs
+deal with, and character encoding is one of the areas in
+which existing machines differ most widely from each other.
+
+To resolve this problem, all input to \.{TIE} is converted to an
+internal seven-bit code that is essentially standard \ASCII{}, the
+``American Standard Code for Information Interchange.'' The conversion
+is done immediately when each character is read in. Conversely,
+characters are converted from \ASCII{} to the user's external
+representation just before they are output. But the algorithm is
+prepared for the usage of eight-bit data.
+
+\noindent Here is a table of the standard visible \ASCII{} codes:
+$$\def\:{\char\count255\global\advance\count255 by 1}
+\count255='40
+\vbox{
+\hbox{\hbox to 40pt{\it\hfill0\/\hfill}%
+\hbox to 40pt{\it\hfill1\/\hfill}%
+\hbox to 40pt{\it\hfill2\/\hfill}%
+\hbox to 40pt{\it\hfill3\/\hfill}%
+\hbox to 40pt{\it\hfill4\/\hfill}%
+\hbox to 40pt{\it\hfill5\/\hfill}%
+\hbox to 40pt{\it\hfill6\/\hfill}%
+\hbox to 40pt{\it\hfill7\/\hfill}}
+\vskip 4pt
+\hrule
+\def\^{\vrule height 10.5pt depth 4.5pt}
+\halign{\hbox to 0pt{\hskip -24pt\O{#0}\hfill}&\^
+\hbox to 40pt{\tt\hfill#\hfill\^}&
+&\hbox to 40pt{\tt\hfill#\hfill\^}\cr
+04&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+05&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+06&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+07&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+10&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+11&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+12&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+13&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+14&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+15&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+16&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+17&\:&\:&\:&\:&\:&\:&\:\cr}
+\hrule width 280pt}$$
+(Actually, of course, code |040| is an invisible blank space.) Code |0136|
+was once an upward arrow (\.{\char'13}), and code |0137| was
+once a left arrow (\.^^X), in olden times when the first draft
+of ASCII code was prepared; but \.{TIE} works with today's standard
+ASCII in which those codes represent circumflex and underline as shown.
+The maximum value used is also defined, it must be changed if an
+extended \ASCII{} is used.
+
+If the \Cl\ compiler is not able to process \&{unsigned char}'s, you
+should define |ASCII_Code| as \&{short}.
+@^system dependencies@>
+
+@<Global types@>=
+#define max_ASCII (@'~'+1)
+typedef unsigned char ASCII_Code;
+ /* eight-bit numbers, a subrange of the integers */
+
+
+@ \Cl\ was first implemented on a machine that uses the
+\ASCII{} representation for characters. But to make it readily
+available also for other machines (big brother is watching?)\
+we add a conversion that may be undone for most installations.
+\.{TIE} assumes that it is being used
+with a character set that contains at least the
+characters of standard \ASCII{} as listed above.
+
+In order to accommodate this difference, we shall use the
+name |text_char| to stand for the data type of the
+characters in the input and output files. We shall also
+assume that |text_char| consists of the elements
+|first_text_char| through |last_text_char|,
+inclusive. The following definitions should be adjusted if
+necessary.
+@^system dependencies@>
+
+@d first_text_char 0 /* ordinal number of the smallest element of |text_char|*/
+@d last_text_char 255 /* ordinal number of the largest element of |text_char|*/
+
+@<Global types@>=
+typedef unsigned char text_char; /* the data type of characters in text files */
+typedef FILE* text_file;
+
+
+@ The \.{TIE} processor converts between \ASCII{} code and
+the user's external character set by means of arrays |xord|
+and |xchr| that are analogous to \PASCAL's |ord| and |chr|
+functions.
+
+The mapping may be disabled by changing the following macro
+definitions to just a cast. If your \Cl\ compiler does not support
+\&{unsigned char}'s, you should incorporate a binary and with |0xff|.
+@^system dependencies@>
+
+@d map_xchr(c) (text_char)(c)
+ /* change this to |xchr[c]| on non \ASCII{} machines */
+@d map_xord(c) (ASCII_Code)(c)
+ /* change this to |xord[c]| on non \ASCII{} machines */
+
+@<Global variables@>=
+static ASCII_Code xord[last_text_char+1];
+ /* specifies conversion of input characters */
+static text_char xchr[max_ASCII+1];
+ /* specifies conversion of output characters */
+
+
+@ If we assume that every system using \.{WEB} is able to
+read and write the visible characters of standard \ASCII{}
+(although not necessarily using the \ASCII{} codes to
+represent them), the following assignment statements
+initialize most of the |xchr| array properly, without
+needing any system-dependent changes. For example, the
+statement |xchr[@'A']='A'| that appears in the present
+\.{WEB} file might be encoded in, say, {\mc EBCDIC} code on
+the external medium on which it resides, but \.{CTANGLE} will
+convert from this external code to \ASCII{} and back again.
+Therefore the assignment statement |xchr[65]='A'| will
+appear in the corresponding \Cl\ file, and \Cl\ will
+compile this statement so that |xchr[65]| receives the
+character \.A in the external code. Note that it
+would be quite incorrect to say |xchr[@'A']=@'A'|, because
+|@'A'| is a constant of type |int| not \&{char}, and
+because we have |@'A'==65| regardless of the external
+character set.
+
+@<Set initial values@>=
+xchr[@' ']=' ';
+xchr[@'!']='!';
+xchr[@'\"']='\"';
+xchr[@'#']='#';@/
+xchr[@'$']='$';
+xchr[@'%']='%';
+xchr[@'&']='&';
+xchr[@'\'']='\'';@/
+xchr[@'(']='(';
+xchr[@')']=')';
+xchr[@'*']='*';
+xchr[@'+']='+';@/
+xchr[@',']=',';
+xchr[@'-']='-';
+xchr[@'.']='.';
+xchr[@'/']='/';@/
+xchr[@'0']='0';
+xchr[@'1']='1';
+xchr[@'2']='2';
+xchr[@'3']='3';@/
+xchr[@'4']='4';
+xchr[@'5']='5';
+xchr[@'6']='6';
+xchr[@'7']='7';@/
+xchr[@'8']='8';
+xchr[@'9']='9';
+xchr[@':']=':';
+xchr[@';']=';';@/
+xchr[@'<']='<';
+xchr[@'=']='=';
+xchr[@'>']='>';
+xchr[@'?']='?';@/
+xchr[@'@@']='@@';
+xchr[@'A']='A';
+xchr[@'B']='B';
+xchr[@'C']='C';@/
+xchr[@'D']='D';
+xchr[@'E']='E';
+xchr[@'F']='F';
+xchr[@'G']='G';@/
+xchr[@'H']='H';
+xchr[@'I']='I';
+xchr[@'J']='J';
+xchr[@'K']='K';@/
+xchr[@'L']='L';
+xchr[@'M']='M';
+xchr[@'N']='N';
+xchr[@'O']='O';@/
+xchr[@'P']='P';
+xchr[@'Q']='Q';
+xchr[@'R']='R';
+xchr[@'S']='S';@/
+xchr[@'T']='T';
+xchr[@'U']='U';
+xchr[@'V']='V';
+xchr[@'W']='W';@/
+xchr[@'X']='X';
+xchr[@'Y']='Y';
+xchr[@'Z']='Z';
+xchr[@'[']='[';@/
+xchr[@'\\']='\\';
+xchr[@']']=']';
+xchr[@'^']='^';
+xchr[@'_']='_';@/
+xchr[@'`']='`';
+xchr[@'a']='a';
+xchr[@'b']='b';
+xchr[@'c']='c';@/
+xchr[@'d']='d';
+xchr[@'e']='e';
+xchr[@'f']='f';
+xchr[@'g']='g';@/
+xchr[@'h']='h';
+xchr[@'i']='i';
+xchr[@'j']='j';
+xchr[@'k']='k';@/
+xchr[@'l']='l';
+xchr[@'m']='m';
+xchr[@'n']='n';
+xchr[@'o']='o';@/
+xchr[@'p']='p';
+xchr[@'q']='q';
+xchr[@'r']='r';
+xchr[@'s']='s';@/
+xchr[@'t']='t';
+xchr[@'u']='u';
+xchr[@'v']='v';
+xchr[@'w']='w';@/
+xchr[@'x']='x';
+xchr[@'y']='y';
+xchr[@'z']='z';
+xchr[@'{']='{';@/
+xchr[@'|']='|';
+xchr[@'}']='}';
+xchr[@'~']='~';@/
+xchr[0]=' '; xchr[0x7F]=' '; /* these \ASCII{} codes are not used */
+
+
+@ Some of the \ASCII{} codes below |0x20| have been given a
+symbolic name in \.{TIE} because they are used with a special
+meaning.
+
+@d tab_mark @'\t' /* \ASCII{} code used as tab-skip */
+@d nl_mark @'\n' /* \ASCII{} code used as line end marker */
+@d form_feed @'\f' /* \ASCII{} code used as page eject */
+
+
+@ When we initialize the |xord| array and the remaining
+parts of |xchr|, it will be convenient to make use of an
+index variable, |i|.
+
+@<Local variables for initialisation@>=
+int i;
+
+
+@ Here now is the system-dependent part of the character
+set. If \.{TIE} is being implemented on a garden-variety
+\Cl\ for which only standard \ASCII{} codes will appear
+in the input and output files, you don't need to make any
+changes here.
+@^system dependencies@>
+
+Changes to the present module will make \.{TIE} more
+friendly on computers that have an extended character set,
+so that one can type things like \.^^Z. If you have an
+extended set of characters that are easily incorporated into
+text files, you can assign codes arbitrarily here, giving an
+|xchr| equivalent to whatever characters the users of
+\.{TIE} are allowed to have in their input files, provided
+that unsuitable characters do not correspond to special
+codes like |tab_mark| that are listed above.
+
+@<Set init...@>=
+for (i=1;i<@' ';xchr[i++]=' ');
+xchr[tab_mark]='\t';
+xchr[form_feed]='\f';
+xchr[nl_mark]='\n';
+
+
+@ The following system-independent code makes the |xord|
+array contain a suitable inverse to the information in
+|xchr|.
+
+@<Set init...@>=
+for ( i=first_text_char ; i<=last_text_char ; xord[i++]=@' ' ) do_nothing;
+for ( i=1 ; i<=@'~' ; i++ ) xord[xchr[i]] = i;
+
+
+
+
+
+@* Input and output.
+
+\noindent Output for the user is done by writing on file |term_out|,
+which is assumed to consist of characters of type \&{text\_char}. It
+should be linked to |stdout| usually. Terminal input is not needed in
+this version of \.{TIE}. |stdin| and |stdout| are predefined if we
+include the \.{stdio.h} definitions. Although I/O redirection for
+|stdout| is usually available you may lead output to another file if
+you change the definition of |term_out|. Also we define some macros
+for terminating an output line and writing strings to the user.
+
+@^system dependencies@>
+@d term_out stdout
+@d print(a) fprintf(term_out,a) /* `|print|' means write on the terminal */
+@d print2(a,b) fprintf(term_out,a,b) /* same with two arguments */
+@d print3(a,b,c) fprintf(term_out,a,b,c) /* same with three arguments */
+@d print_c(v) fputc(v,term_out); /* print a single character */
+@d new_line(v) fputc('\n',v) /* start new line */
+@d term_new_line new_line(term_out)
+ /* start new line of the terminal */
+@d print_ln(v) {fprintf(term_out,v);term_new_line;}
+ /* `|print|' and then start new line */
+@d print2_ln(a,b) {print2(a,b);term_new_line;} /* same with two arguments */
+@d print3_ln(a,b,c) {print3(a,b,c);term_new_line;}
+ /* same with three arguments */
+@d print_nl(v) {term_new_line; print(v);}
+ /* print information starting on a new line */
+@d print2_nl(a,b) {term_new_line; print2(a,b);}
+ /* same for two arguments */
+
+@<Global |#include|s@>=
+#include <stdio.h>
+
+
+@ And we need dynamic memory allocation.
+This should cause no trouble in any \Cl\ program.
+@^system dependencies@>
+
+@<Global |#include|s@>=
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+@ The |update_terminal| function is called when we want to
+make sure that everything we have output to the terminal so
+far has actually left the computer's internal buffers and
+been sent.
+@^system dependencies@>
+
+@d update_terminal fflush(term_out) /* empty the terminal output buffer */
+
+
+
+
+
+@* Data structures.
+
+\noindent The multiple 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 \.{TIE} 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)| */
+
+
+@ Two more types will indicate variables used as an index into either
+the file buffer or the file table.
+
+@<Global types@>=
+typedef int buffer_index; /* |-1..buf_size| */
+typedef int file_index; /* |-1..max_file_index+1| */
+
+
+@ The following data structure joins all informations needed to use
+these input files.
+%`line' is a normal identifier throughout this program
+@f line dummy
+@<Global types@>=
+typedef struct _idsc{
+ string name_of_file;
+ ASCII_Code buffer[buf_size];
+ in_file_modes mode;
+ long line;
+ file_types type_of_file;
+ buffer_index limit;
+ text_file the_file;
+ } input_description;
+
+
+@ These data types are used in the global variable section.
+They refer to the files in action, the number of change files,
+the mode of operation and the current output state.
+
+@<Global variables@>=
+static file_index actual_input,test_input,no_ch;
+static file_types prod_chf=unknown;
+static out_md_type out_mode;
+
+
+@ All input files (including the master file) are recorded
+in the following structure.
+Mostly the components are accessed through a local pointer variable.
+This corresponds to \PASCAL's \&{with}-statement
+and results in a one-time-computation of the index expression.
+
+@<Global variables@>=
+static input_description *input_organization[max_file_index+1];
+
+
+
+
+
+@* File I/O.
+
+\noindent 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.
+
+@<Internal functions@>=
+void get_line(i)
+ file_index i;
+{register input_description *inp_desc=input_organization[i];
+ if (inp_desc->mode==ignore) return;
+ if (feof(inp_desc->the_file))
+ @<Handle end of file and return@>@;
+ @<Get line into buffer@>@;
+}
+
+
+@ 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=-1; /* mark end-of-file */
+ if (inp_desc->type_of_file==master) input_has_ended=true;
+ return;
+}
+
+
+@ This variable must be declared for global access.
+
+@<Global variables@>=
+static boolean input_has_ended=false;
+
+
+@ 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@>=
+{int final_limit; /* used to delete trailing spaces */
+ int c; /* the actual character read */
+ @<Increment the line number and print a progess report at
+ certain times@>@;
+ inp_desc->limit=final_limit=0;
+ while (inp_desc->limit<buf_size) {
+ c=fgetc(inp_desc->the_file);
+ @<Check |c| for |EOF|, |return| if line was empty, otherwise
+ |break| to process last line@>@;
+ inp_desc->buffer[inp_desc->limit++]=c=map_xord(c);
+ if (c==nl_mark) break; /* end of line found */
+ if (c!=@' ' && c!=tab_mark)
+ final_limit=inp_desc->limit;
+ }
+ @<Test for truncated line, skip to end of line@>@;
+ inp_desc->limit=final_limit;
+}
+
+
+@ 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 ...@>=
+incr(inp_desc->line);
+if (inp_desc->type_of_file==master && inp_desc->line % 100==0) {
+ if (inp_desc->line % 500 == 0) print2("%ld",inp_desc->line);
+ else print_c('.');
+ update_terminal;
+}
+
+
+@ There may be incomplete lines of the editor used does
+not make sure that the last character before end of file
+is an end of line. In such a case we must process the
+final line. Of the current line is empty, we just can \&{return}.
+Note that this test must be done {\sl before} the character read
+is translated.
+@^system dependencies@>
+
+@<Check |c| for |EOF|...@>=
+ if (c==EOF) {
+ if (inp_desc->limit<=0) {
+ inp_desc->mode=ignore;
+ inp_desc->limit=-1; /* mark end-of-file */
+ if (inp_desc->type_of_file==master) input_has_ended=true;
+ return;
+ } else { /* add end of line mark */
+ c=nl_mark;
+ break;
+ }
+ }
+
+
+@ If the line is truncated we must skip the rest
+(and still watch for |EOF|!).
+@<Test for truncated line, skip to end of line@>=
+if (c!=nl_mark) {
+ err_print("! Input line too long")(i);
+@.Input line too long@>
+ while ( (c=fgetc(inp_desc->the_file)) != EOF && map_xord(c) != nl_mark )
+ do_nothing; /* skip to end */
+ }
+
+
+
+
+
+@* Reporting errors to the user.
+
+\noindent 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("! Error message")(file_no)|;}
+$$
+where |file_no| is the number of the file which is concerned by the
+error. Please note that no trailing dot is supplied by the error
+message because it is appended by |err_print|.
+
+This function is implemented as a macro. It gives a message and an
+indication of the offending file. The actions to determine the error
+location are provided by a function called |err_loc|.
+
+@d error_loc(m) err_loc(m); history=troublesome; @+ }
+@d err_print(m) { @+ print_nl(m); error_loc
+
+@<Error handling...@>=
+void err_loc(i) /* prints location of error */
+ int i;
+{
+ print3_ln(" (file %s, l.%ld).",
+ input_organization[i]->name_of_file,
+ input_organization[i]->line);
+}
+
+
+@ Non recoverable errors are handled by calling |fatal_error| that
+outputs a message and then calls `|jump_out|'. |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(m) {
+ print(m); print_c('.'); history=fatal;
+ term_new_line; jump_out();
+ }
+
+
+@ |jump_out| just cuts across all active procedure levels and jumps
+out of the program. It is used when no recovery from a particular
+error has been provided. The return code from this program should be
+regarded by the caller.
+
+@d jump_out() exit(1)
+
+
+
+
+
+@* Handling multiple change files.
+
+\noindent 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) {
+ fatal_error("! Could not open/create output file");
+@.Could not open/create output file@>
+ }
+}
+
+
+@ The name of the file and the file desciptor are stored in
+global variables.
+
+@<Global variables@>=
+static text_file out_file;
+static string out_name;
+
+
+@ For the master file we start just reading its first line
+into the buffer, if we could open it.
+
+@<Get the master file started@>=
+{ input_organization[0]->the_file=
+ fopen(input_organization[0]->name_of_file,"r");
+ if (input_organization[0]->the_file==NULL)
+ fatal_error("! Could not open master file");
+@.Could not open master file@>
+ print2("(%s)",input_organization[0]->name_of_file);
+ term_new_line;
+ input_organization[0]->type_of_file=master;
+ get_line(0);
+}
+
+@ For the change files we must skip the comment part and
+see, whether we can find any change in it.
+This is done by |init_change_file|.
+
+@<Prepare the change files@>=
+{file_index i;
+ i=1;
+ while (i<no_ch) {
+ input_organization[i]->the_file=
+ fopen(input_organization[i]->name_of_file,"r");
+ if (input_organization[i]->the_file==NULL)
+ fatal_error("!Could not open change file");
+@.Could not open change file@>
+ print2("(%s)",input_organization[i]->name_of_file);
+ term_new_line;
+ init_change_file(i,true);
+ incr(i);
+ }
+}
+
+
+
+
+
+@*Input/output organization.
+
+\noindent Here's a simple function that checks if two lines
+are different.
+
+@<Internal functions@>=
+boolean lines_dont_match(i,j)
+ file_index i,j;
+{
+ buffer_index k,lmt;
+ if (input_organization[i]->limit != input_organization[j]->limit)
+ return(true);
+ lmt=input_organization[i]->limit;
+ for ( k=0 ; k<lmt ; k++ )
+ if (input_organization[i]->buffer[k] != input_organization[j]->buffer[k])
+ return(true);
+ return(false);
+}
+
+
+@ Function |init_change_file(i,b)| is used to ignore all
+lines of the input file with index |i| until the next change
+module is found. The boolean parameter |b| indicates
+whether we do not want to see \.{@@x} or \.{@@y} entries during
+our skip.
+
+@<Internal functions@>=
+void init_change_file(i,b)
+ file_index i; boolean b;
+{register input_description *inp_desc=input_organization[i];
+ @<Skip over comment lines; |return| if end of file@>@;
+ @<Skip to the next nonblank line; |return| if end of file@>@;
+}
+
+
+@ 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} or \.{@@z} (which would
+probably indicate that the change file is fouled up).
+
+@<Skip over comment lines...@>=
+loop@+ {ASCII_Code c;
+ get_line(i);
+ if (inp_desc->mode==ignore) return;
+ if (inp_desc->limit<2) continue;
+ if (inp_desc->buffer[0] != @'@@') continue;
+ c=inp_desc->buffer[1];
+ if (c>=@'X' && c<=@'Z')
+ c+=@'z'-@'Z'; /*lowercasify*/
+ if (c==@'x') break;
+ if (c==@'y' || c==@'z')
+ if (b) /* scanning for start of change */
+ err_print("! Where is the matching @@x?")(i);
+@.Where is the match...@>
+}
+
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do{
+ get_line(i);
+ if (inp_desc->mode==ignore) {
+ err_print("! Change file ended after @@x")(i);
+@.Change file ended...@>
+ return;
+ }
+} while (inp_desc->limit<=0);
+
+
+@ 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;
+{buffer_index i; /* index into the buffer */
+ buffer_index lmt; /* line length */
+ ASCII_Code *p; /* output pointer */
+ lmt=input_organization[j]->limit;
+ p=input_organization[j]->buffer;
+ for (i=0;i<lmt;i++) fputc(map_xchr(*p++),out_file);
+ new_line(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_organization[i];
+ if (inp_desc->limit<0) {
+ print_nl("! At the end of change file missing @@z ");
+@.At the end of change file...@>
+ print2("%s",input_organization[i]->name_of_file);
+ term_new_line;
+ return(true);
+ } else if (inp_desc->limit>=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_organization[i];
+ if (inp_desc->limit>=2 && inp_desc->buffer[0]==@'@@')
+ if (inp_desc->buffer[1]==@'Y'||inp_desc->buffer[1]==@'y') return(true);
+ return(false);
+}
+
+
+
+@ To process the input file the next section
+reads a line of the actual input file and updates the
+|input_organization| for all files with index |test_file| greater
+|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 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 inactive if
+it reaches end of file.
+
+@<Check the...@>=
+{register input_description *inp_desc;
+while (actual_input>0 && e_of_ch_module(actual_input)) {
+ inp_desc=input_organization[actual_input];
+ if (inp_desc->type_of_file==master) {
+ /* emergency exit, everything mixed up!*/
+ fatal_error("! This can't happen: change file is master file");
+@.This can't happen...@>
+ }
+ inp_desc->mode=search;
+ init_change_file(actual_input,true);
+ while ((input_organization[actual_input]->mode!=reading
+ && actual_input>0)) decr(actual_input);
+}
+}
+
+
+@ Now we will set |test_input| to the file that has another match
+for the current line. This depends on the state of the other
+change files. If no other file matches, |actual_input| refers to
+a line to write and |test_input| ist set to |none|.
+
+@d none (max_file_index+1)
+
+@<Scan all other files...@>=
+test_input=none;
+test_file=actual_input;
+while (test_input==none && test_file<no_ch-1){
+ incr(test_file);
+ switch (input_organization[test_file]->mode) {
+ case search: if (lines_dont_match(actual_input,test_file)==false) {
+ input_organization[test_file]->mode=test;
+ test_input=test_file;
+ }
+ break;
+ case test: if (lines_dont_match(actual_input, test_file)==true) {
+ /* error, sections do not match */
+ input_organization[test_file]->mode=search;
+ err_print("! Sections do not match")(actual_input);
+@.Sections do not match@>
+ err_loc(test_file);
+ init_change_file(test_file,false);
+ } else test_input=test_file;
+ break;
+ case reading: do_nothing; /* this can't happen */
+ break;
+ case ignore: do_nothing; /* nothing to do */
+ break;
+ }
+}
+
+
+@ For the output we must distinguish whether we create a new change
+file or a new master file. The change file creation needs some closer
+inspection because we may be before a change, in the pattern part or
+in the replacement part. For a master file we have to write the line
+from the current actual input.
+
+@<Handle output@>=
+if (prod_chf==chf) {
+ loop @+ {
+ @<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 must be done.
+
+@<Test for normal...@>=
+if (out_mode==normal) {
+ if (test_input!=none) {
+ fputc(map_xchr(@'@@'),out_file); fputc(map_xchr(@'x'),out_file);
+ new_line(out_file);
+ out_mode=pre;
+ } else break;
+}
+
+
+@ Check whether we have to start the replacement text.
+This is the case when we have no more matching line.
+Otherwise the master file source line must be copied to the
+change file.
+@<Test for pre...@>=
+
+ if (out_mode==pre) {
+ if (test_input==none) {
+ fputc(map_xchr(@'@@'),out_file); fputc(map_xchr(@'y'),out_file);
+ new_line(out_file);
+ out_mode=post;
+ } else {
+ if (input_organization[actual_input]->type_of_file==master)
+ put_line(actual_input);
+ break;
+ }
+ }
+
+
+@ Check whether an entry from a change file is complete.
+If the current change was a change for a change file in effect,
+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_organization[actual_input]->type_of_file==chf) {
+ if (test_input==none) put_line(actual_input);
+ break;
+ } else {
+ fputc(map_xchr(@'@@'),out_file); fputc(map_xchr(@'z'),out_file);
+ new_line(out_file);
+ new_line(out_file);
+ 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);
+if (test_input!=none) {
+ get_line(test_input);
+ if (e_of_ch_preamble(test_input)==true) {
+ get_line(test_input); /* update current changing file */
+ input_organization[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 */
+ fputc(map_xchr(@'@@'),out_file); fputc(map_xchr(@'z'),out_file);
+ new_line(out_file);
+ }
+
+
+@ 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_organization[i]->mode!=ignore)
+ err_print("! Change file entry did not match")(i);
+@.Change file entry ...@>
+ }
+}
+
+
+@ We want to tell the user about our command line options. This is
+done by the |usage()| function. It contains merely the necessary
+print statement and exits afterwards.
+
+@<Intern...@>=
+void usage()
+{
+ print("Usage: tie -[mc] outfile master changefile(s)");
+ term_new_line;
+ jump_out();
+}
+
+
+@ 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 5~parameters and can handle up to |max_file_index|
+change files. The names fo the file parameters will be inserted into
+the structure of |input_organization|. 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_organization| 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@>=
+{int act_arg;
+ if ( argc < 5 || argc > max_file_index+4-1 ) usage();
+ no_ch = -1; /* fill this part of |input_organization| */
+ for ( act_arg=1 ; act_arg<argc ; act_arg++ ) {
+ if (argv[act_arg][0]=='-') @<Set a flag@>@;
+ else @<Get a file name@>@;
+ }
+ if (no_ch<=0|| prod_chf==unknown) usage();
+}
+
+
+@ 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();
+else
+ switch (argv[act_arg][1]) {
+ case 'c':
+ case 'C': prod_chf=chf; break;
+ case 'm':
+ case 'M': prod_chf=master; break;
+ default: usage();
+ }
+
+
+@ We have to distinguish whether this is the very first file name
+(known if |no_ch==(-1)|) or if the next element of |input_organization|
+must be filled.
+
+@<Get a file name@>=
+{ if (no_ch==(-1)) {
+ out_name=argv[act_arg];
+ } else { register input_description *inp_desc;
+ inp_desc=(input_description *)
+ malloc(sizeof(input_description));
+ if (inp_desc==NULL)
+ fatal_error("! No memory for descriptor");
+@.No memory for descriptor@>
+ inp_desc->mode=search;
+ inp_desc->line=0;
+ inp_desc->type_of_file=chf;
+ inp_desc->limit=0;
+ inp_desc->name_of_file=argv[act_arg];
+ input_organization[no_ch]=inp_desc;
+ }
+ incr(no_ch);
+}
+
+
+@* The main program.
+
+\noindent Here is where \.{TIE} starts, and where it ends.
+
+@<The main function@>=
+main(argc,argv)
+ int argc; string *argv;
+{{@<Local variables for initialisation@>@;
+ @<Set initial...@>@;
+ }
+ print_ln(banner); /* print a ``banner line'' */
+ print_ln(copyright); /* include the copyright notice */
+ actual_input=0;
+ out_mode=normal;
+ @<Scan the parameters@>@;
+ @<Prepare the output file@>@;
+ @<Get the master file started@>@;
+ @<Prepare the change files@>@;
+ @<Process the input@>@;
+ @<Check that all changes have been read@>@;
+ @<Print the job |history|@>@;
+}
+
+@ We want to pass the |history| value to the operating system so that
+it can be used to govern whether or not other programs are started.
+Additionaly we report the history to the user, although this may not
+be ``{\mc UNIX}'' style---but we are in best companion: \.{WEB} and
+\TeX{} do the same.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+{string msg;
+ switch (history) {
+ case spotless: msg="No errors were found"; break;
+ case troublesome: msg="Pardon me, but I think I spotted something wrong.";
+ break;
+ case fatal: msg="That was a fatal error, my friend"; break;
+ } /* there are no other cases */
+ print2_nl("(%s.)",msg); term_new_line;
+ exit ( history == spotless ? 0 : 1 );
+}
+
+
+
+
+
+@* System-dependent changes.
+
+\noindent This section should be replaced, if necessary, by
+changes to the program that are necessary to make \.{TIE}
+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.
+
+\noindent Here is the cross-reference table for the \.{TIE}
+processor.
diff --git a/Build/source/texk/web2c/tiedir/tiedoc.tex b/Build/source/texk/web2c/tiedir/tiedoc.tex
new file mode 100644
index 00000000000..40cb9198ac1
--- /dev/null
+++ b/Build/source/texk/web2c/tiedir/tiedoc.tex
@@ -0,0 +1,176 @@
+% tiedoc.tex 26 Oct 89
+%------------------------
+
+% 89-10-26 js: changed description of user interface which was altered
+% in the rewrite of TIE in CWEB.
+% 88-12-?? kg: first release
+
+
+
+\documentstyle{article}
+
+\let\mc=\small
+\def\TANGLE{{\tt TANGLE}}
+\def\TIE{{\tt TIE}}
+\def\WEAVE{{\tt WEAVE}}
+\def\WEB{{\tt WEB}}
+\def\CWEB{{\mc CWEB}}
+\def\PASCAL{Pascal}
+
+
+\begin{document}
+
+\title{The \TIE{} Processor}
+\author{Klaus Guntermann\\
+TH Darmstadt\\
+Fachbereich Informatik\\
+Institut f\"ur Theoretische Informatik}
+\date{October 1989}
+
+\maketitle
+
+
+
+\section{Introduction}
+
+To install a program on a computer usually
+system dependent changes are needed.
+The systems of the \WEB{} family allows to describe these changes in a
+so called change file.
+To incorporate the changes into the program \TANGLE\ processes
+the original source file and inserts the changes into the proper places.
+
+Sometimes it is good practice to develop a set of change files to be able to
+distinguish between different changes like
+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.
+
+The processors \TANGLE\ and \WEAVE\ can handle only one change file.
+The combination of change files is done best in another preprocessing step.
+\TIE\ is able to create either a new master file or a single change file that
+comprises the effect of all change files.
+
+Since \TIE\ does not know anything about \WEB\ programs but only about the
+structure of change files, it is possible to use this program for other
+programming languages as well.
+You just pretend that you want to create a new master file and \TIE\ will go
+and insert all the changes from your change files.
+
+
+
+\section{Application}
+
+The current version of \TIE\ accepts a master file and up to 9 change files.
+Because in general it is important to use the changes in their proper sequence
+the order of the files must be chosen carefully.
+
+\TIE{} must be called with at least 4~parameters:
+%
+\begin{enumerate}
+
+\item either the option {\tt -c\/} or {\tt -m}. This option controls if
+a change file or a 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). At least one must be present.
+
+\end{enumerate}
+
+The multiple change files are used as if the single change files were
+merged into the master files step by step. Thus more than 9 change
+files might be incorporated by repeated application of \TIE. Of
+course you may change the constant {\it max\_file\_index\/} in \TIE{}
+which defines the maximum number of change files, too.
+
+Please note that even when multiple change files are processed each of
+the files is read only once. For each of the change files and for the
+master file there is only one line in memory at a time (neglecting
+operating system buffering). Thus the storage requirement of \TIE\
+does not depend on the size of the change files or the size of a
+single changed section.
+
+
+\newpage
+
+
+\def\eof{$\langle${\mc EOF}$\rangle$}
+\tabcolsep=1em
+
+
+\section{Example}
+
+To illustrate the actions \TIE\ performs you may inspect the following
+example that exercises some of the border line cases.
+
+\begin{center}
+\begin{tabular}{llll}
+\multicolumn1{c}{\sc Master}&
+ \multicolumn1{c}{\tt CF1}&
+ \multicolumn1{c}{\tt CF2}&
+ \multicolumn1{c}{\tt 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\\
+line 6 &changed line 3 &line 4 &\eof\\
+line 7 &inserted line &@y\\
+line 8 &@z &final line 2\\
+line 9 & &final line 3\\
+line 10 &@x &changed line 4\\
+\eof &line 7 &@z\\
+ &@y\\
+ &changed line 7 &@x\\
+ &@z &changed line 7\\
+ &\eof &line 8\\
+ & &@y\\
+ & &final line 7\\
+ & &final line 8\\
+ & &@z\\
+ & &\eof\\
+\end{tabular}
+\end{center}
+
+
+\newpage
+
+
+Using these input files and running \TIE\ twice to create a new master
+file and a new change file will result in the following output files:
+
+\begin{center}
+\begin{tabular}{ll}
+\multicolumn1{c}{\sc Master}&
+ \multicolumn1{c}{\sc Change}\\[1pt]
+\hline
+final line 2 &@x\\
+final line 3 &line 1\\
+final line 4 &line 2\\
+line 5 &line 3\\
+line 6 &line 4\\
+final line 7 &@y\\
+final line 8 &final line 2\\
+line 9 &final line 3\\
+line 10 &final line 4\\
+\eof &@z\\
+ &\\
+ &@x\\
+ &line 7\\
+ &line 8\\
+ &@y\\
+ &final line 7\\
+ &final line 8\\
+ &@z\\
+ &\eof\\
+\end{tabular}
+\end{center}
+
+
+
+\end{document}