% % This is the distribution file for Cameron Smith's "wrtfile" utility. % Running TeX on this file causes it to write out the files that % make up the "wrtfile" distribution. % % Go ahead and try it; it will ask permission before writing anything. % % This distribution file is dated 19 October 1992. % %%%%%%%%%%%%%%%%%%%%% % % ARCHIVISTS PLEASE TAKE NOTE: % % The entire contents of this file are Copyright 1992 by Cameron Smith. % This file may be distributed freely *in its original form*. % % Executing this file with the TeX processor causes portions of this file % to be written out to other files; but these constituent files may *NOT* % be distributed individually, nor assembled together in any other form % than this, if the distribution is to be called "wrtfile". % % The computer code embodied in this file may be used freely for any % purpose without fee, and may be incorporated into other works, % provided that such works are not represented as the "wrtfile" TeX utility. % % In other words, use it, enjoy it, build on it any way you want, but % if you want to redistribute "wrtfile" as such, you must distribute % it *only* in the form of this TeX file. % %%%%%%%%%%%%%%%%%%%%% % \begingroup \catcode`\@ 11 \gdef\FILE #1 {% \@@FILESETUP \let\@@WRITELINE\@@FILEWRITELINE \let\@@ENDFILE\@@FILEEOF \immediate\openout 0 #1\relax \message{\string\FILE\space #1}% \@@READLINE } \gdef\TYPE{% \@@FILESETUP \let\@@WRITELINE\@@TYPELINE \let\@@ENDFILE\@@TYPEEOF \@@STARTTYPE } \gdef\@@FILESETUP{% \begingroup \endlinechar`\^^M \def\do##1{\catcode`##1 12 }% \dospecials \catcode`\^^I 12 \catcode`\^^L 12 \catcode`\^^M 12\relax \newlinechar`\^^M \def\empty{}% } \endlinechar -1 \catcode `\^^M 12 \relax \catcode `\| 0 \relax \catcode `\\ 12 |relax |gdef|@@STARTTYPE#1^^M{|@@READLINE} |gdef|@@READLINE#1^^M{ |@@TESTLINE#1^^M\EOF } |gdef|@@TESTLINE#1\EOF{ |def|@@TEST{#1} |ifx|@@TEST|empty % \EOF occurred at start of line |let|next|@@ENDFILE |else |def|next{|@@WRITELINE#1\EOF} |fi |next } |gdef|@@FILEWRITELINE#1^^M\EOF{ |immediate|write 0{#1} |@@READLINE } |gdef|@@TYPELINE#1^^M\EOF{ |immediate|write 16{#1} |@@READLINE } |gdef|@@FILEEOF#1^^M\EOF{ |immediate|closeout 0|relax |endgroup |message{\EOF} } |gdef|@@TYPEEOF#1^^M\EOF{ |endgroup } |endgroup \TYPE This is the distribution file for Cameron Smith's "wrtfile" utility. Running TeX on this file causes it to write out the files that make up the "wrtfile" distribution. This distribution file is dated 19 October 1992. In a moment you'll be asked whether you wish to proceed. If you say yes, this job will write the following files: read.me -- you should read this! wrtfile.doc -- file-writing code, with comments explaining how it works wrtfile.tex -- same code, with comments stripped out for speed If you already have files by these names, you may wish to stop and rename the files or move them elsewhere so they don't get overwritten. Say "y" or "yes" to proceed, anything else to stop the job. \EOF \message{Do you wish to proceed? } \read -1 to \answer \def\getans #1 #2\endanswer{\uppercase{\def\answer{#1}}} \expandafter\getans\answer\endanswer \newif\ifYES \def\ansY{Y} \def\ansYES{YES} \ifx\answer\ansY \YEStrue \else\ifx\answer\ansYES \YEStrue \fi\fi \ifYES \let\next\relax \else \let\next\end \message{Job aborted.}% \fi \next \TYPE The files will now be written. Please read the file "read.me"! It explains what "wrtfile" is for, how it works, what you may do with it, and limitations on its redistribution. Thanks! \EOF \FILE read.me WRTFILE ======= by Cameron Smith version of 19 October 1992 HISTORY OF WRTFILE ------------------ Volume 92, Issue 37 of the UKTeX Digest (Friday, 9 Oct 1992) included a trio of utilities by Jonathan Fine . These were commcheck.tex, plainind.tex, and filechop.tex. I found them all interesting and useful, especially filechop.tex, which makes it easy to write a TeX file that writes out other files when TeXed. But I was dissatisfied with the way Mr. Fine's filechop was implemented, because it used TeX's parameter-collection mechanism to gather up the information to be written out. This approach made Fine's code very simple, but it placed severe constraints on the amount of material that could be written to a file -- no more than what could be accommodated in TeX's parameter memory. If memory overflow did occur, the TeX job would be aborted ungracefully. I decided to implement a more robust file writing utility. My file-writing algorithm reads and writes one line at a time. The code is more complicated than Fine's and executes more slowly, but it can write files of any length (provided that no single line is longer than TeX's input buffer can accommodate). In the course of developing wrtfile I realized that the same code that allows us to write to a file also makes it easy to write to the terminal, so I implemented that as well. It's useful in "driver files" (like the one that created this file!) to be able to conveniently present several lines of information to the user. The name "wrtfile" was chosen in deference to the 8-character naming limitations of MS-DOS. May that system soon perish from the world! HOW DOES IT WORK? ----------------- Put the code for "wrtfile" into a TeX document. It defines two control sequences that are meant to be invoked by users (and several more "internal" macros that are not meant to be called directly). The \FILE macro takes as an argument a file name, opens up a file of that name for writing, and writes the lines that follow it in the source file to that output file until it encounters a line beginning with "\EOF". For example, the lines \FILE abc.def Mary had a little lamb, its fleece was white as snow. \EOF would cause the file "abc.def" to be created, and to contain the two lines "Mary had a little lamb," and "its fleece was white as snow.". All of TeX's special characters (such as \, ~, &, {, }, $, and %) are disabled during this operation -- the writing stops only when the literal string "\EOF" appears. Furthermore, this string must appear flush at the left margin; it will not be recognized anywhere else. And it will be detected even if it is immediately followed by other non-blank characters: the "abc" in "\EOFabc" would not prevent this string from terminating the writing of a file if it occurred at the left end of a line. The \TYPE macro works like the \FILE macro, except that it takes no argument, and writes to the terminal and the log file rather than creating another file. For example, the lines \TYPE Mary had a little lamb, its fleece was white as snow. \EOF would cause the two lines "Mary had a little lamb," and "its fleece was white as snow." to be written to the terminal and into the log file. For technical reasons, \TYPE should appear on a line by itself. It actually uses TeX's parameter-collection mechanism to remove the end-of-line character that TeX places at the end of each input line; this is necessary because TeX puts the character there as soon as the line is read into TeX's input buffer, before the \TYPE macro gains control. Similarly the \FILE macro should be followed by nothing except the name of the file to be written, which should not contain blanks. Any characters following an \EOF marker on the same line are discarded (because they have been read with funny \catcode values and so are probably not useful). WHAT CAN I DO WITH IT? ---------------------- Although there might be several reasons why one would want to be able to write a verbatim segment of a TeX input file out to another file, the most obvious one that springs to mind is that of distributing TeX macro packages. Ideally, the distribution of a TeX package should include several files: * two versions of the executable code, one heavily commented for ease of understanding and one with comments stripped out for speed of execution, * a user manual (comments explaining the workings of the code are no replacement for this!), which explains the features of the package and how to use them, * one or more sample files that can be processed by TeX to show how the package should be used in real applications, * (in some cases) source code in C or Pascal or another language providing utilities to be used with the macro package, and possibly other files according to the needs and nature of the package. But it is inconvenient and unreliable to distribute all of these files separately. One runs the risk that archives may get out of synch, updating some files but not others when new versions are released, or that users may retrieve only some of the files they need -- often they get the program but not the documentation, resulting in unnecessary pleas for help. (Those who *get* the documentation but won't *read* it are a different problem, alas.) On the whole it is much better to distribute software in a single package, which the recipient can break apart to generate the several files that are needed. There are, of course, many utilities for assembling collections of files into single files for transmission or archiving. But they suffer from various drawbacks. Many are tied to specific systems and so are unsuitable for distributing TeX code, since TeX is implemented on so many disparate systems. Also, such utilities typically create binary files; such files cannot be transmitted through email, and some archives do not accept them. (When I was preparing to distribute my "pageframe" LaTeX utility, the first archivist I approached told me that his site had a policy against placing any non-ASCII file into its archives, and so would accept the ".tar.Z" file I submitted only if I agreed to have the constituent files broken out and made available for individual retrieval. Since I did NOT want it to be possible for a user to retrieve the code without the documentation, I was unhappy about this.) Suppose you want to distribute a file that "wrtfile" can't write? (See the "Bugs and Limitations" section below.) One possibility is to encode the file, use "wrtfile" to write the encoded version, and tell recipients how to decode it. For example, the "uuencode" utility reads a file containing any sequence of bytes and writes a file that contains only standard printable characters. The companion "uudecode" utility can read the printable file created by "uuencode" and reconstruct the original file. "uuencode" and "uudecode" originated in UNIX environments, but freeware implementations of them for VMS, Macintosh, and MS-DOS systems have been available for some time. Other formats ("xxencode", "btoa", "vvencode", etc.) with similar purposes are also in use. Incidentally, the file-writing functionality provided by "wrtfile" is similar to, but more primitive than, the capability provided by the "docstrip" utility of Mittelbach, Duchier, and Braams. However, "docstrip" works best when it is guided by a "driver" file, separate from the "package" file from which other files are extracted. That puts us back in the position of having to distribute two files (the driver and the package file), keep them in synch, and make sure that anyone who gets either file gets both. Also, many sites do not have the "docstrip" code, and its creators have placed restrictions on its distribution that make it impractical to include a copy with your own package so that all your recipients will have it. (It is not permitted to send "docstrip.sty" without sending the entire "doc.doc" and "docstrip.doc" distribution set, which is prohibitively large.) By contrast, the code for "wrtfile" is only about sixty lines long -- a little over 1K -- and may be freely incorporated into document packages. (See the section below on "Redistribution".) BUGS AND LIMITATIONS -------------------- There are two respects in which the files written by \FILE are not faithful copies of the original data. Neither one has any negative effect if the files being written are going to be read only by TeX. Fixing either one would require changes to TeX itself. The two discrepancies pertain to the handling of trailing blanks and "non-printable" characters. Trailing blanks on an input line will be chopped off. This is a feature of TeX's input routine, and happens even before category codes are assigned. (TeX was made to behave this way to accommodate operating systems that handle text files as files of fixed-length records; such systems usually pad the lines of text files with blanks to fill them out to a common length. By stripping off all trailing blanks on all input lines, TeX is guaranteed to behave the same way whether lines are padded or not.) Since the code for \FILE never receives the trailing blanks in the first place, it can't know to write them out, so they don't appear in the output file. So this method of writing a file will not faithfully reproduce files that have lines with trailing blanks. On the other hand, the same fact about TeX that creates this problem means that the deleted trailing blanks could never have influenced TeX anyway, so if the file being written is destined to be TeX input then this blank removal doesn't matter. TeX writes some "non-printable" characters as special sequences involving the "^^" notation. The choice of which character codes get written this way is implementation-dependent -- it may vary from one machine or one implementation to another, but for each implementation it is fixed at compile time and isn't changeable later. In Unix TeX the tab character is always written as "^^I", for example. This is another respect in which the lines written out by TeX may not faithfully reconstruct the original input, but again it doesn't matter as long as the files being written are going to be read in as TeX input later, because TeX's reading mechanism converts the "^^" notation back into the original characters as the lines are read. REDISTRIBUTION OF WRTFILE ------------------------- ARCHIVISTS PLEASE TAKE NOTE! The entire contents of the "wrtfile" distribution package are copyright 1992 by Cameron Smith, with all rights reserved. Permission to use the code, without fee, for any purpose, is hereby given, subject to one restriction: the "wrtfile" package itself must not be distributed in any other form than that of the "wrtfdist.tex" distribution file. In other words, you are free to use the unadorned "wrtfile.tex" code to create a distribution package file that (when processed by TeX) produces a collection of your own files, and you are free to distribute such a package file that contains the "wrtfile" code. But you must not claim to distribute "wrtfile" itself unless you distribute it in its original form (as a "wrtfile" package). You may not, for instance, distribute "wrtfile" by collecting the three files "read.me", "wrtfile.tex", and "wrtfile.doc" into a .zip or .tar.Z archive file and making that file available for FTP or email retrieval. MAINTENANCE: BUG REPORTS AND FIXES ---------------------------------- The author of wrtfile intends to maintain it, and would be very grateful to receive error reports and suggestions for enhancement. His name is Cameron Smith. You can contact him via electronic mail as cameron@symcom.math.uiuc.edu (on the Internet) or by telephone at 513-429-2707 (in the USA). \EOF read.me \FILE wrtfile.doc % The "wrtfile" code and comments are copyright 1992 by Cameron Smith. % Please read the file "read.me" for limitations on use and redistribution. % % We'll be doing some monkey business with catcodes and other parameters, % but we want to keep it local. % \begingroup % % Allow @ signs in macro names % \catcode`\@ 11 % % The \FILE macro gets things going. % It scoops up the name of the file to write, % reassigns catcodes of special characters, % makes sure that the \endlinechar, the \newlinechar, and % the macro \empty have their expected meanings, % opens the output file, writes a message to the terminal, % and starts the reading loop. % \gdef\FILE #1 {% \@@FILESETUP \let\@@WRITELINE\@@FILEWRITELINE \let\@@ENDFILE\@@FILEEOF \immediate\openout 0 #1\relax \message{\string\FILE\space #1}% \@@READLINE } % % \TYPE does the same things that \FILE does, but it outputs to the % terminal (and the log file) rather than to another file. It's % handy for putting explanatory passages into the master file. % It uses the same reading loop as \FILE, but takes slightly % different actions when writing a line and at end-of-file. % \gdef\TYPE{% \@@FILESETUP \let\@@WRITELINE\@@TYPELINE \let\@@ENDFILE\@@TYPEEOF \@@STARTTYPE } % % This does the actual re-catcoding of characters and other setup % that both \FILE and \TYPE need. % \gdef\@@FILESETUP{% \begingroup \endlinechar`\^^M \def\do##1{\catcode`##1 12 }% \dospecials \catcode`\^^I 12 \catcode`\^^L 12 \catcode`\^^M 12\relax \newlinechar`\^^M \def\empty{}% } % % Henceforth we don't want any character added to the ends of lines. % Note: this applies while we are *defining* this code, not executing it! % When \@@FILESETUP is executed it sets the \endlinechar to ^^M. % \endlinechar -1 % % Within these definitions, make ^^M an "other" character, % | a macro escape character, and \ an "other" character. % \catcode `\^^M 12 \relax \catcode `\| 0 \relax \catcode `\\ 12 |relax % |gdef|@@STARTTYPE#1^^M{|@@READLINE} % % The \@@READLINE macro reads up to the next ^^M character % (which is guaranteed to be present because \FILE sets \endlinechar) % and hands off the line to \@@TESTLINE, after introducing the characters % "\EOF" (note: "\" is an ordinary character now!) so that \@@TESTLINE % will definitely find those characters. % % NOTE: Trailing blanks on an input line will be chopped off, and % some "non-printable" characters will be written as special % sequences involving the "^^" notation. See the "read.me" file % distributed with this code for a discussion of these matters. % |gdef|@@READLINE#1^^M{ |@@TESTLINE#1^^M\EOF } % % \@@TESTLINE scans up to the first "\EOF" sequence (\@@READLINE has % ensured that we will find one). If nothing (not even ^^M or spaces) % precedes "\EOF", then we have found the end-of-file mark, and we call % \@@ENDFILE. Otherwise we haven't found the end-of-file mark, so we call % \@@WRITELINE to write the line to the output file and then resume the % reading loop. If we call \@@WRITELINE, we must be very careful to % put back the tokens that were swallowed by \@@TESTLINE, including the % "\EOF" sequence (which might not have come from the tokens inserted % by \@@READLINE, if "\EOF" occurred in the input line somwhere other than % at the left end). Note that spaces are not ignored at the beginnings of % lines while this code is executing, so the "\EOF" sequence must be flush % at the left end of the line to be recognized as the end-of-file mark. % On the other hand, it will be recognized at the left end of the line % even if it is followed by alphabetic characters: the "abc" in "\EOFabc" % would not keep \@@TESTLINE from recognizing the "\EOF". % |gdef|@@TESTLINE#1\EOF{ |def|@@TEST{#1} |ifx|@@TEST|empty % \EOF occurred at start of line |let|next|@@ENDFILE |else |def|next{|@@WRITELINE#1\EOF} |fi |next } % % \@@WRITELINE writes the line we just read, minus the end-of-line ^^M % character and the "\EOF" sequence introduced by \@@READLINE, to the % output file. % |gdef|@@FILEWRITELINE#1^^M\EOF{ |immediate|write 0{#1} |@@READLINE } % % \@@TYPELINE does what \@@WRITELINE does, but it writes to the terminal % and the log file rather than to another file. % |gdef|@@TYPELINE#1^^M\EOF{ |immediate|write 16{#1} |@@READLINE } % % Note: tokens following an \EOF that begins a line are thrown away! % They have been read with funny catcodes, so they aren't likely % to be useful anyway. This lets us put a "comment" there, which is % useful for flagging which file the \EOF is supposed to be ending. % |gdef|@@FILEEOF#1^^M\EOF{ |immediate|closeout 0|relax |endgroup |message{\EOF} } % % We don't have to close a file if we were writing to the terminal. % |gdef|@@TYPEEOF#1^^M\EOF{ |endgroup } % % Revert to previous values of \endlinechar, catcodes, etc. % |endgroup % % End of the file-chopping code. % \EOF wrtfile.doc \FILE wrtfile.tex % The "wrtfile" code is copyright 1992 by Cameron Smith. % Please read the file "read.me" for limitations on use and redistribution. \begingroup \catcode`\@ 11 \gdef\FILE #1 {% \@@FILESETUP \let\@@WRITELINE\@@FILEWRITELINE \let\@@ENDFILE\@@FILEEOF \immediate\openout 0 #1\relax \message{\string\FILE\space #1}% \@@READLINE } \gdef\TYPE{% \@@FILESETUP \let\@@WRITELINE\@@TYPELINE \let\@@ENDFILE\@@TYPEEOF \@@STARTTYPE } \gdef\@@FILESETUP{% \begingroup \endlinechar`\^^M \def\do##1{\catcode`##1 12 }% \dospecials \catcode`\^^I 12 \catcode`\^^L 12 \catcode`\^^M 12\relax \newlinechar`\^^M \def\empty{}% } \endlinechar -1 \catcode `\^^M 12 \relax \catcode `\| 0 \relax \catcode `\\ 12 |relax |gdef|@@STARTTYPE#1^^M{|@@READLINE} |gdef|@@READLINE#1^^M{ |@@TESTLINE#1^^M\EOF } |gdef|@@TESTLINE#1\EOF{ |def|@@TEST{#1} |ifx|@@TEST|empty % \EOF occurred at start of line |let|next|@@ENDFILE |else |def|next{|@@WRITELINE#1\EOF} |fi |next } |gdef|@@FILEWRITELINE#1^^M\EOF{ |immediate|write 0{#1} |@@READLINE } |gdef|@@TYPELINE#1^^M\EOF{ |immediate|write 16{#1} |@@READLINE } |gdef|@@FILEEOF#1^^M\EOF{ |immediate|closeout 0|relax |endgroup |message{\EOF} } |gdef|@@TYPEEOF#1^^M\EOF{ |endgroup } |endgroup \EOF wrtfile.tex \end