[The TUGboat article mentioned below appeared as [info not yet available--18-Aug-1994]] Date: 17 Mar 1994 13:04:36 -0500 (EST) From: Michael Downes Subject: Around the Bend #17, answers To: info-tex@shsu.edu X-ListName: TeX-Related Network Discussion List Exercise 17 (posted January 14) asked for an error recovery file to provide better recovery from file input errors: When TeX cannot find an input file, it prompts for an alternative file name and refuses to continue until a valid file name is entered or the user presses some (system-dependent) abort key. This can be rather unfriendly, especially for novice users. At the request of Barbara Beeton (TUGboat's editor) I wrote up the results of this exercise as an article for publication in TUGboat, so this posting will be largely redundant with that article. ------------------------------------- DON'T BOTHER, REDEFINE \input INSTEAD Interestingly, both of the answers I received (from Victor Eijkhout and Donald Arseneau) recommended redefining input instead of trying to make an input error recovery file. Donald summed it up thus: > Since verbatim file input is an important mainstream application, > the task is hopeless. > > The right approach is to redefine \input and check for the file's > existence at the macro level. I.e., consider the way a typical \verbfile commands works: first, start a group; next, deactivate all special characters such as \ { } # % by changing their catcodes; then input the desired file; and finally close the group to restore normal catcodes. If the desired file is not found and an input error recovery file is read instead, the IERF will not be able to do anything because of the deactivation of \ { } etc. ---------------------------------------------- DIFFICULTIES ASSOCIATED WITH REDEFINING \input Generally speaking I am in favor of redefining input (for instance, to make up for the deficiency in TeX that the current input file name is not accessible like \jobname or \inputlineno), but there are some practical problems: ---In order to serve all users, the redefinition of \input would have to go into plain TeX, LaTeX, and any other major macro packages that are not layered on top of plain TeX or LaTeX. ---The most commonly used approach to test for the existence of an input file is \openin N=file.name \ifeof N ..., but for some TeX implementations \openin will only open a file in the current directory, and not search through the entire `TeX inputs' path. I believe that this restriction is canonical in TeX.web therefore only overridden by the system-dependent changes of each TeX implementation according to the judgment of the individual implementor. ---The details of how to redefine \input are nontrivial. If you redefine \input to take an argument delimited by a space, for example, there is some risk of bombing on existing files with statements like \input x.y\relax It becomes especially nontrivial if you want to use some method other than simple \openin ... \ifeof to test for file existence, so that the method will be reliable across all systems. It is worth noting that in LaTeX2e the \input command has been dramatically overhauled so that it solves, among other things, some of the problems mentioned here. Anyone doubting the claim that the work is nontrivial is invited to look at the LaTeX2e definitions. ---Redefining \input will (generally speaking) not help for the jobname file itself. When the file name is given on the command line, or following a ** prompt, the input operation is done directly by TeX instead of through invoking the control sequence \input. ---When a non-existing file is called for by a verb-file command, TeX will prompt the user for a file name, and then if a .tex recovery file exists, pressing will typeset the contents of that file; but this is at least as good as inputting a null file, in that you are not stuck at the prompt with no obvious way to quit. ---------------------------------------------------------- SOMEBODY ALREADY PUBLISHED SOME INPUT ERROR RECOVERY FILES Coincidentally, reading through one of my books a few days after posting Around the Bend #17, I found that someone had already written and published a suite of input error recovery files: Frank Mittelbach, The LaTeX Companion, section 14-4. ------------------------------------------------------ BUT WHAT THE HECK, HERE ARE MY SLIGHTLY DIFFERENT ONES The basic idea is to create a file named h.tex that will produce an \errmessage{...} statement. Copies (or links) of this file will be made under several different names corresponding to the typical user responses to an input file error, to the extent that the operating system permits. So a first attempt would be something like this: \errmessage{Enter x to exit or ? to see other options} Suppose we test this with a simple test file: % This is line 1 % This is line 2 \input fzrg \relax % This is line 3 % This is line 4 \end The on-screen result looks like this: ! I can't find file `fzrg.tex'. l.3 \input fzrg \relax % This is line 3 Please type another input file name: h (h.tex ! Enter x to exit or ? to see other options. l.1 ... to exit or ? to see other options} ? Then if the user enters ? they will see Type to proceed, S to scroll future error messages, R to run without stopping, Q to run quietly, I to insert something, E to edit your file, 1 or ... or 9 to ignore the next 1 to 9 tokens of input, H for help, X to quit. ? x Now let's examine this solution a little more closely, to ask what are the potential problems, and what assumptions can be done away with? One problem is the possibility of an unusual catcode for space, question mark, left brace, right brace, backslash, or \endlinechar. For the backslash (and the letters) we don't have much choice; if they don't have normal catcodes, h.tex cannot issue an \errmessage command, or even try to fix up the catcodes. (This is why the problem of verbatim file input is insoluble, if primitive \input is used.) Note that for users of a macro package such as texinfo, which has @ for the escape character instead of backslash, a different IERF would be required. The \endlinechar problem can be solved by adding a percent sign at the end of the line: \errmessage{...}% but at the cost of a new assumption: percent must have catcode 14. This and some of the other catcode assumptions can be removed with a bit of extra work: \begingroup\chardef\%37\catcode\%14\chardef\ 32\catcode\ 10\relax% \catcode123 1\catcode125 2\catcode63 12 % \errmessage{% Enter x to exit or ? to see other options}% \endgroup\endinput% This enforces the desired catcodes for space, %, {, }, and ?; and putting % at the end of each line makes \endlinechar harmless, no matter what its prevailing value and catcode might happen to be. The \begingroup ... \endgroup pair of course keep the catcode changes local, just in case (though I expect that the user will normally choose to exit anyway). I write \chardef\%37\catcode\%14 in preference to the alternatives \catcode37 14 \catcode37=14 \catcode37'16 \catcode37"E \catcode`\%14 which require assuming a usable catcode for one extra character (space or = or ' or ...). Even using \string, as in \catcode37\string"E would fail if " had catcode 5, 9, 10, 11, 14, or 15. Here now is the screen output produced by the above IERF: ! I can't find file `fzrg'. l.3 \input fzrg \relax % This is line 3 Please type another input file name: h (h.tex ! Enter x to exit or ? to see other options. l.5 Enter x to exit or ? to see other options} % ? x ------------------ BEST FINAL VERSION There is one fairly obvious drawback of the above IERF: the error message is repeated twice on screen, once by \errmessage and once in the error context shown for line 5. There is a little trick that can be used to fix that: Use only the error context for showing the message text, by putting it in a comment rather than in the argument of \errmessage! [Cf.the comment after \patterns in the original TeX hyphenation patterns file hyphen.tex.] \begingroup\chardef\%37\catcode\%14\chardef\?63\catcode\?12\relax% \chardef\{123\catcode\{1\chardef\ 32\catcode\ 2\relax% \errmessage{Input\string canceled\string ..% % Enter x to exit or ? to see other options % \endgroup\endinput% I have thrown in some extra cleverness with the catcode of space to clean up the screen output a tiny bit more. The result looks like this: ! I can't find file `fzrg'. l.3 \input fzrg \relax % This is line 3 Please type another input file name: h (h.tex ! Input canceled ... l.4 % Enter x to exit or ? to see other options % ? x Frank Mittelbach's IERF solution differs from mine by providing a set of files that attempt to mimic standard TeX error recovery according to their name: The file s.tex, for example, arranges to switch into \scrollmode and continue processing, as would happen if you entered `s' at a normal error message prompt. And there are files named e.tex, x.tex, q.tex that mimic the corresponding error message actions. His IERFs also don't bother to worry about possible odd catcodes for {, space, }, etc.---an approach whose simplicity perhaps outweighs the minor added robustness of my version. ----------- CONCLUSIONS It seems that it would be a worthy service to their users if the authors of all TeX implementations took a second look at how input file errors are handled and added suitable actions depending on the operating system. For example, under DOS it is difficult to create a file named .tex, so perhaps emTeX, PCTeX, TurboTeX, etc., should check for the case when the user presses the key at the prompt, and automatically exit instead of trying to input a highly improbable file! Similar arguments would hold for an input file name of ? or ?.tex for operating systems where ? is an OS wild-card character. And another part of improving the input error handling might be to add to their standard distributions a set of IERFs in the TeX inputs area, to help users who are using some macro package *other* than LaTeX2e. (Or, even for LaTeX2e users, to help in the case when it is the jobname file itself that was not input-able.) I recommend of course my IERF given above; my feelings would not be deeply wounded, however, if Frank's version gets used instead. Installing either version would be much better for end users than none at all. Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~