diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/web2c/ctiedir | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (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/ChangeLog | 119 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/Makefile | 51 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/README | 75 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie-k.ch | 727 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.1 | 55 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.c | 1111 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.cf1 | 14 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.cf2 | 26 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.cf3 | 13 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.chf.gen | 26 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.inc | 4 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.inc1 | 1 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.inc2 | 1 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.master.gen | 19 | ||||
-rwxr-xr-x | Build/source/texk/web2c/ctiedir/ctie.test | 20 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.tie | 16 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctie.w | 1280 | ||||
-rw-r--r-- | Build/source/texk/web2c/ctiedir/ctiedoc.tex | 242 |
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} |