diff options
author | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
---|---|---|
committer | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
commit | c6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch) | |
tree | 1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/texk/web2c/luatexdir/tex/texfileio.c | |
parent | 07ee7222e389b0777456b427a55c22d0e6ffd267 (diff) |
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex/texfileio.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/tex/texfileio.c | 1509 |
1 files changed, 0 insertions, 1509 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/texfileio.c b/Build/source/texk/web2c/luatexdir/tex/texfileio.c deleted file mode 100644 index 4e0677a564b..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texfileio.c +++ /dev/null @@ -1,1509 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -#include <string.h> -#include <kpathsea/absolute.h> - -/*tex - -The bane of portability is the fact that different operating systems treat input -and output quite differently, perhaps because computer scientists have not given -sufficient attention to this problem. People have felt somehow that input and -output are not part of ``real'' programming. Well, it is true that some kinds of -programming are more fun than others. With existing input/output conventions -being so diverse and so messy, the only sources of joy in such parts of the code -are the rare occasions when one can find a way to make the program a little less -bad than it might have been. We have two choices, either to attack I/O now and -get it over with, or to postpone I/O until near the end. Neither prospect is very -attractive, so let's get it over with. - -The basic operations we need to do are (1)~inputting and outputting of text, to -or from a file or the user's terminal; (2)~inputting and outputting of eight-bit -bytes, to or from a file; (3)~instructing the operating system to initiate -(``open'') or to terminate (``close'') input or output from a specified file; -(4)~testing whether the end of an input file has been reached. - -\TeX\ needs to deal with two kinds of files. We shall use the term |alpha_file| -for a file that contains textual data, and the term |byte_file| for a file that -contains eight-bit binary information. These two types turn out to be the same on -many computers, but sometimes there is a significant distinction, so we shall be -careful to distinguish between them. Standard protocols for transferring such -files from computer to computer, via high-speed networks, are now becoming -available to more and more communities of users. - -The program actually makes use also of a third kind of file, called a -|word_file|, when dumping and reloading base information for its own -initialization. We shall define a word file later; but it will be possible for us -to specify simple operations on word files before they are defined. - -We finally did away with |nameoffile| and |namelength|, but the variables have to -be kept otherwise there will be link errors from |openclose.c| in the web2c -library - -*/ - -char *nameoffile; -int namelength; - -/*tex - - When input files are opened via a callback, they will also be read using - callbacks. for that purpose, the |open_read_file_callback| returns an integer - to uniquely identify a callback table. This id replaces the file point |f| in - this case, because the input does not have to be a file in the traditional - sense. - - Signalling this fact is achieved by having two arrays of integers. - -*/ - -int *input_file_callback_id; -int read_file_callback_id[17]; - -/*tex - - Here we handle |-output-directory|. We assume that it is OK to look here - first. Possibly it would be better to replace lookups in "." with lookups in - the |output_directory| followed by "." but to do this requires much more - invasive surgery in libkpathsea. - -*/ - -static char *find_in_output_directory(const char *s) -{ - if (output_directory && !kpse_absolute_p(s, false)) { - FILE *f_ptr; - char *ftemp = concat3(output_directory, DIR_SEP_STRING, s); - /*tex This code is used for input files only. */ - f_ptr = fopen(ftemp, "rb"); - if (f_ptr) { - fclose(f_ptr); - return ftemp; - } else { - free(ftemp); - - } - } - return NULL; -} - -/*tex - - Find an \.{\\input} or \.{\\read} file. |n| differentiates between those - case. - -*/ - -int kpse_available(const char *m) { - if (!kpse_init) { - fprintf(stdout,"missing kpse replacement callback '%s', quitting\n",m); - exit(1); - } - return 1 ; -} - -char *luatex_find_read_file(const char *s, int n, int callback_index) -{ - char *ftemp = NULL; - int callback_id = callback_defined(callback_index); - if (callback_id > 0) { - (void) run_callback(callback_id, "dS->R", n, s, &ftemp); - } else if (kpse_available("find_read_file")) { - /*tex Use kpathsea here. */ - ftemp = find_in_output_directory(s); - if (!ftemp) - ftemp = kpse_find_file(s, kpse_tex_format, 1); - } - if (ftemp) { - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = xstrdup(ftemp); - } - return ftemp; -} - -/*tex Find other files types. */ - -char *luatex_find_file(const char *s, int callback_index) -{ - char *ftemp = NULL; - int callback_id = callback_defined(callback_index); - if (callback_id > 0) { - (void) run_callback(callback_id, "S->R", s, &ftemp); - } else if (kpse_available("find_read_file")) { - /*tex Use kpathsea here. */ - switch (callback_index) { - case find_enc_file_callback: - ftemp = kpse_find_file(s, kpse_enc_format, 0); - break; - case find_map_file_callback: - ftemp = kpse_find_file(s, kpse_fontmap_format, 0); - break; - case find_type1_file_callback: - ftemp = kpse_find_file(s, kpse_type1_format, 0); - break; - case find_truetype_file_callback: - ftemp = kpse_find_file(s, kpse_truetype_format, 0); - break; - case find_opentype_file_callback: - ftemp = kpse_find_file(s, kpse_opentype_format, 0); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_truetype_format, 0); - break; - case find_data_file_callback: - ftemp = find_in_output_directory(s); - if (!ftemp) - ftemp = kpse_find_file(s, kpse_tex_format, 1); - break; - case find_font_file_callback: - ftemp = kpse_find_file(s, kpse_ofm_format, 1); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_tfm_format, 1); - break; - case find_vf_file_callback: - ftemp = kpse_find_file(s, kpse_ovf_format, 0); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_vf_format, 0); - break; - case find_cidmap_file_callback: - ftemp = kpse_find_file(s, kpse_cid_format, 0); - break; - default: - printf("luatex_find_file(): do not know how to handle file %s of type %d\n", s, callback_index); - break; - } - } - return ftemp; -} - -/*tex - - \LUATEX\ used to have private functions for these that did not use kpathsea, - but since the file paranoia tests have to come from kpathsea anyway, that is - no longer useful. The only downside to using luatex is that if one wants to - disable kpathsea via the Lua startup script, it is now an absolute - requirement that all file discovery callbacks are specified. Just using the - find_read_file, but not setting open_read_file, for example, does not work - any more if kpathsea is not to be used at all. - -*/ - -#define openoutnameok(A) kpse_out_name_ok (A) -#define openinnameok(A) kpse_in_name_ok (A) - -/*tex - - Open an input file F, using the kpathsea format FILEFMT and passing - |FOPEN_MODE| to fopen. The filename is in `fn'. We return whether or not the - open succeeded. - -*/ - -boolean luatex_open_input(FILE ** f_ptr, const char *fn, int filefmt, const_string fopen_mode, boolean must_exist) -{ - /*tex We haven't found anything yet. */ - string fname = NULL; - *f_ptr = NULL; - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = NULL; - fname = kpse_find_file(fn, (kpse_file_format_type) filefmt, must_exist); - if (fname) { - fullnameoffile = xstrdup(fname); - /*tex - - If we found the file in the current directory, don't leave the `./' - at the beginning of `fn', since it looks dumb when `tex foo' says - `(./foo.tex ... )'. On the other hand, if the user said `tex ./foo', - and that's what we opened, then keep it -- the user specified it, so - we shouldn't remove it. - - */ - if (fname[0] == '.' && IS_DIR_SEP(fname[1]) && (fn[0] != '.' || !IS_DIR_SEP(fn[1]))) { - unsigned i = 0; - while (fname[i + 2] != 0) { - fname[i] = fname[i + 2]; - i++; - } - fname[i] = 0; - } - /*tex This fopen is not allowed to fail. */ - *f_ptr = xfopen(fname, fopen_mode); - } - if (*f_ptr) { - recorder_record_input(fname); - } - return *f_ptr != NULL; -} - -boolean luatex_open_output(FILE ** f_ptr, const char *fn, const_string fopen_mode) -{ - char *fname; - boolean absolute = kpse_absolute_p(fn, false); - /*tex If we have an explicit output directory, use it. */ - if (output_directory && !absolute) { - fname = concat3(output_directory, DIR_SEP_STRING, fn); - } else { - fname = xstrdup(fn); - } - /*tex Is the filename openable as given? */ - *f_ptr = fopen(fname, fopen_mode); - if (!*f_ptr) { - /*tex Can't open as given. Try the envvar. */ - string texmfoutput = kpse_var_value("TEXMFOUTPUT"); - if (texmfoutput && *texmfoutput && !absolute) { - fname = concat3(texmfoutput, DIR_SEP_STRING, fn); - *f_ptr = fopen(fname, fopen_mode); - } - } - if (*f_ptr) { - recorder_record_output(fname); - } - free(fname); - return *f_ptr != NULL; -} - -boolean lua_a_open_in(alpha_file * f, char *fn, int n) -{ - int k; - char *fnam; - int callback_id; - boolean ret = true; - boolean file_ok = true; - if (n == 0) { - input_file_callback_id[iindex] = 0; - } else { - read_file_callback_id[n] = 0; - } - if (*fn == '|') - fnam = fn; - else - fnam = luatex_find_read_file(fn, n, find_read_file_callback); - if (!fnam) - return false; - callback_id = callback_defined(open_read_file_callback); - if (callback_id > 0) { - k = run_and_save_callback(callback_id, "S->", fnam); - if (k > 0) { - ret = true; - if (n == 0) - input_file_callback_id[iindex] = k; - else - read_file_callback_id[n] = k; - } else { - /*tex read failed */ - file_ok = false; - } - } else { - /*tex no read callback */ - if (openinnameok(fn)) { - ret = open_in_or_pipe(f, fnam, kpse_tex_format, FOPEN_RBIN_MODE, (n == 0 ? true : false)); - } else { - /*tex open failed */ - file_ok = false; - } - } - if (!file_ok) { - ret = false; - } - return ret; -} - -boolean lua_a_open_out(alpha_file * f, char *fn, int n) -{ - boolean test; - char *fnam = NULL; - int callback_id; - boolean ret = false; - callback_id = callback_defined(find_write_file_callback); - if (callback_id > 0) { - test = run_callback(callback_id, "dS->R", n, fn, &fnam); - if ((test) && (fnam != NULL) && (strlen(fnam) > 0)) { - /*tex - - There is no message here because if that is needed the macro - package should do that in the callback code. As elsewhere, - messaging is left to \LUA\ then. - - */ - ret = open_outfile(f, fnam, FOPEN_W_MODE); - free(fnam); - } - } else { - if (openoutnameok(fn)) { - if (n > 0 && selector != term_only) { - /*tex - - This message to the log is for downward compatibility with - other tex's as there are scripts out there that act on this - message. An alternative is to let a macro package write an - explicit message. - - */ - fprintf(log_file,"\n\\openout%i = %s\n",n-1,fn); - } - ret = open_out_or_pipe(f, fn, FOPEN_W_MODE); - } - } - return ret; -} - -boolean lua_b_open_out(alpha_file * f, char *fn) -{ - boolean test; - char *fnam = NULL; - int callback_id; - boolean ret = false; - callback_id = callback_defined(find_output_file_callback); - if (callback_id > 0) { - test = run_callback(callback_id, "S->R", fn, &fnam); - if ((test) && (fnam != NULL) && (strlen(fnam) > 0)) { - ret = open_outfile(f, fnam, FOPEN_WBIN_MODE); - free(fnam); - } - } else { - if (openoutnameok(fn)) { - ret = luatex_open_output(f, fn, FOPEN_WBIN_MODE); - } - } - return ret; -} - -void lua_a_close_in(alpha_file f, int n) -{ - int callback_id; - if (n == 0) - callback_id = input_file_callback_id[iindex]; - else - callback_id = read_file_callback_id[n]; - if (callback_id > 0) { - run_saved_callback(callback_id, "close", "->"); - destroy_saved_callback(callback_id); - if (n == 0) - input_file_callback_id[iindex] = 0; - else - read_file_callback_id[n] = 0; - } else { - close_file_or_pipe(f); - } -} - -void lua_a_close_out(alpha_file f) -{ - close_file_or_pipe(f); -} - -/*tex - - Binary input and output are done with C's ordinary procedures, so we don't - have to make any other special arrangements for binary~I/O. Text output is - also easy to do with standard routines. The treatment of text input is more - difficult, however, because of the necessary translation to |ASCII_code| - values. \TeX's conventions should be efficient, and they should blend nicely - with the user's operating environment. - - Input from text files is read one line at a time, using a routine called - |lua_input_ln|. This function is defined in terms of global variables called - |buffer|, |first|, and |last| that will be described in detail later; for - now, it suffices for us to know that |buffer| is an array of |ASCII_code| - values, and that |first| and |last| are indices into this array representing - the beginning and ending of a line of text. - -*/ - -/*tex lines of characters being read */ - -packed_ASCII_code *buffer; - -/*tex the first unused position in |buffer| */ - -int first; - -/*tex end of the line just input to |buffer| */ - -int last; - -/*tex largest index used in |buffer| */ - -int max_buf_stack; - -/*tex - - The |lua_input_ln| function brings the next line of input from the specified - file into available positions of the buffer array and returns the value - |true|, unless the file has already been entirely read, in which case it - returns |false| and sets |last:=first|. In general, the |ASCII_code| numbers - that represent the next line of the file are input into |buffer[first]|, - |buffer[first+1]|, \dots, |buffer[last-1]|; and the global variable |last| is - set equal to |first| plus the length of the line. Trailing blanks are removed - from the line; thus, either |last=first| (in which case the line was entirely - blank) or |buffer[last-1]<>" "|. - - An overflow error is given, however, if the normal actions of |lua_input_ln| - would make |last>=buf_size|; this is done so that other parts of \TeX\ can - safely look at the contents of |buffer[last+1]| without overstepping the - bounds of the |buffer| array. Upon entry to |lua_input_ln|, the condition - |first<buf_size| will always hold, so that there is always room for an - ``empty'' line. - - The variable |max_buf_stack|, which is used to keep track of how large the - |buf_size| parameter must be to accommodate the present job, is also kept up - to date by |lua_input_ln|. - - If the |bypass_eoln| parameter is |true|, |lua_input_ln| will do a |get| - before looking at the first character of the line; this skips over an |eoln| - that was in |f^|. The procedure does not do a |get| when it reaches the end - of the line; therefore it can be used to acquire input from the user's - terminal as well as from ordinary text files. - - Since the inner loop of |lua_input_ln| is part of \TeX's ``inner - loop''---each character of input comes in at this place---it is wise to - reduce system overhead by making use of special routines that read in an - entire array of characters at once, if such routines are available. - -*/ - -boolean lua_input_ln(alpha_file f, int n, boolean bypass_eoln) -{ - boolean lua_result; - int last_ptr; - int callback_id; - /*tex Todo: variable can be removed: */ - (void) bypass_eoln; - if (n == 0) - callback_id = input_file_callback_id[iindex]; - else - callback_id = read_file_callback_id[n]; - if (callback_id > 0) { - last = first; - last_ptr = first; - lua_result = - run_saved_callback(callback_id, "reader", "->l", &last_ptr); - if ((lua_result == true) && (last_ptr != 0)) { - last = last_ptr; - if (last > max_buf_stack) - max_buf_stack = last; - } else { - lua_result = false; - } - } else { - lua_result = input_ln(f, bypass_eoln); - } - if (lua_result == true) { - /*tex Fix up the input buffer using callbacks */ - if (last >= first) { - callback_id = callback_defined(process_input_buffer_callback); - if (callback_id > 0) { - last_ptr = first; - lua_result = - run_callback(callback_id, "l->l", (last - first), - &last_ptr); - if ((lua_result == true) && (last_ptr != 0)) { - last = last_ptr; - if (last > max_buf_stack) - max_buf_stack = last; - } - } - } - return true; - } - return false; -} - -/*tex - - We need a special routine to read the first line of \TeX\ input from the - user's terminal. This line is different because it is read before we have - opened the transcript file; there is sort of a ``chicken and egg'' problem - here. If the user types `\.{\\input paper}' on the first line, or if some - macro invoked by that line does such an \.{\\input}, the transcript file will - be named `\.{paper.log}'; but if no \.{\\input} commands are performed during - the first line of terminal input, the transcript file will acquire its - default name `\.{texput.log}'. (The transcript file will not contain error - messages generated by the first line before the first \.{\\input} command.) - - The first line is special also because it may be read before \TeX\ has input - a format file. In such cases, normal error messages cannot yet be given. The - following code uses concepts that will be explained later. - - Different systems have different ways to get started. But regardless of what - conventions are adopted, the routine that initializes the terminal should - satisfy the following specifications: - - \startitemize[n] - - \startitem - It should open file |term_in| for input from the terminal. (The file - |term_out| will already be open for output to the terminal.) - \stopitem - - \startitem - If the user has given a command line, this line should be considered - the first line of terminal input. Otherwise the user should be - prompted with `\.{**}', and the first line of input should be - whatever is typed in response. - \stopitem - - \startitem - The first line of input, which might or might not be a command line, - should appear in locations |first| to |last-1| of the |buffer| array. - \stopitem - - \startitem - The global variable |loc| should be set so that the character to be - read next by \TeX\ is in |buffer[loc]|. This character should not be - blank, and we should have |loc<last|. - \stopitem - - \stopitemize - - It may be necessary to prompt the user several times before a non-blank line - comes in. The prompt is `\.{**}' instead of the later `\.*' because the - meaning is slightly different: `\.{\\input}' need not be typed immediately - after~`\.{**}'.) - - The following program does the required initialization. Iff anything has been - specified on the command line, then |t_open_in| will return with |last > - first|. - -*/ - -boolean init_terminal(void) -{ - /*tex This gets the terminal input started. */ - t_open_in(); - if (last > first) { - iloc = first; - while ((iloc < last) && (buffer[iloc] == ' ')) - incr(iloc); - if (iloc < last) { - return true; - } - } - while (1) { - wake_up_terminal(); - fputs("**", term_out); - update_terminal(); - if (!input_ln(term_in, true)) { - /*tex This shouldn't happen. */ - fputs("\n! End of file on the terminal... why?\n", term_out); - return false; - } - iloc = first; - while ((iloc < last) && (buffer[iloc] == ' ')) { - incr(iloc); - } - /*tex Return unless the line was all blank. */ - if (iloc < last) { - return true; - } - fputs("Please type the name of your input file.\n", term_out); - } -} - - -/*tex - - Here is a procedure that asks the user to type a line of input, assuming that - the |selector| setting is either |term_only| or |term_and_log|. The input is - placed into locations |first| through |last-1| of the |buffer| array, and - echoed on the transcript file if appropriate. - -*/ - -void term_input(void) -{ - /*tex Index into |buffer|: */ - int k; - /*tex Now the user sees the prompt for sure: */ - update_terminal(); - if (!input_ln(term_in, true)) - fatal_error("End of file on the terminal!"); - /*tex The user's line ended with \.{<return>}: */ - term_offset = 0; - /*tex Prepare to echo the input. */ - decr(selector); - if (last != first) { - for (k = first; k <= last - 1; k++) - print_char(buffer[k]); - } - print_ln(); - /*tex Restore previous status. */ - incr(selector); -} - -/*tex - - It's time now to fret about file names. Besides the fact that different - operating systems treat files in different ways, we must cope with the fact - that completely different naming conventions are used by different groups of - people. The following programs show what is required for one particular - operating system; similar routines for other systems are not difficult to - devise. - - \TeX\ assumes that a file name has three parts: the name proper; its - ``extension''; and a ``file area'' where it is found in an external file - system. The extension of an input file or a write file is assumed to be - `\.{.tex}' unless otherwise specified; it is `\.{.log}' on the transcript - file that records each run of \TeX; it is `\.{.tfm}' on the font metric files - that describe characters in the fonts \TeX\ uses; it is `\.{.dvi}' on the - output files that specify typesetting information; and it is `\.{.fmt}' on - the format files written by \.{INITEX} to initialize \TeX. The file area can - be arbitrary on input files, but files are usually output to the user's - current area. If an input file cannot be found on the specified area, \TeX\ - will look for it on a special system area; this special area is intended for - commonly used input files like \.{webmac.tex}. - - Simple uses of \TeX\ refer only to file names that have no explicit extension - or area. For example, a person usually says `\.{\\input} \.{paper}' or - `\.{\\font\\tenrm} \.= \.{helvetica}' instead of `\.{\\input} \.{paper.new}' - or `\.{\\font\\tenrm} \.= \.{<csd.knuth>test}'. Simple file names are best, - because they make the \TeX\ source files portable; whenever a file name - consists entirely of letters and digits, it should be treated in the same way - by all implementations of \TeX. However, users need the ability to refer to - other files in their environment, especially when responding to error - messages concerning unopenable files; therefore we want to let them use the - syntax that appears in their favorite operating system. - - The following procedures don't allow spaces to be part of file names; but - some users seem to like names that are spaced-out. System-dependent changes - to allow such things should probably be made with reluctance, and only when - an entire file name that includes spaces is ``quoted'' somehow. - - Here are the global values that file names will be scanned into. - -*/ - -/*tex name of file just scanned */ - -str_number cur_name; - -/*tex file area just scanned, or \.{""} */ - -str_number cur_area; - -/*tex file extension just scanned, or \.{""} */ - -str_number cur_ext; - -/*tex - - The file names we shall deal with have the following structure: If the name - contains `\./' or `\.:' (for Amiga only), the file area consists of all - characters up to and including the final such character; otherwise the file - area is null. If the remaining file name contains `\..', the file extension - consists of all such characters from the last `\..' to the end, otherwise the - file extension is null. - - We can scan such file names easily by using two global variables that keep - track of the occurrences of area and extension delimiters: - -*/ - -/*tex the most recent `\./', if any */ - -pool_pointer area_delimiter; - -/*tex the relevant `\..', if any */ - -pool_pointer ext_delimiter; - -/*tex - - Input files that can't be found in the user's area may appear in a standard - system area called |TEX_area|. Font metric files whose areas are not given - explicitly are assumed to appear in a standard system area called - |TEX_font_area|. $\Omega$'s compiled translation process files whose areas - are not given explicitly are assumed to appear in a standard system area. - These system area names will, of course, vary from place to place. - -*/ - -#define append_to_fn(A) do { \ - c=(A); \ - if (c!='"') { \ - if (k<file_name_size) fn[k++]=(unsigned char)(c); \ - } \ - } while (0) - - -char *pack_file_name(str_number n, str_number a, str_number e) -{ - /*tex character being packed */ - ASCII_code c; - /*tex index into |str_pool| */ - unsigned char *j; - /*tex number of positions filled in |fn| */ - int k = 0; - unsigned char *fn = xmallocarray(packed_ASCII_code, str_length(a) + str_length(n) + str_length(e) + 1); - for (j = str_string(a); j < str_string(a) + str_length(a); j++) - append_to_fn(*j); - for (j = str_string(n); j < str_string(n) + str_length(n); j++) - append_to_fn(*j); - for (j = str_string(e); j < str_string(e) + str_length(e); j++) - append_to_fn(*j); - fn[k] = 0; - return (char *) fn; -} - -/*tex - - A messier routine is also needed, since format file names must be scanned - before \TeX's string mechanism has been initialized. We shall use the global - variable |TEX_format_default| to supply the text for default system areas and - extensions related to format files. - - Under \UNIX\ we don't give the area part, instead depending on the path - searching that will happen during file opening. Also, the length will be set - in the main program. - -*/ - -char *TEX_format_default; - - -/*tex - - This part of the program becomes active when a ``virgin'' \TeX\ is trying to - get going, just after the preliminary initialization, or when the user is - substituting another format file by typing `\.\&' after the initial `\.{**}' - prompt. The buffer contains the first line of input in - |buffer[loc..(last-1)]|, where |loc<last| and |buffer[loc]<>" "|. - -*/ - -char *open_fmt_file(void) -{ - /*tex The first space after the format file name: */ - int j; - char *fmt = NULL; - int dist; - j = iloc; - if (buffer[iloc] == '&') { - incr(iloc); - j = iloc; - buffer[last] = ' '; - while (buffer[j] != ' ') - incr(j); - fmt = xmalloc((unsigned) (j - iloc + 1)); - strncpy(fmt, (char *) (buffer + iloc), (size_t) (j - iloc)); - fmt[j - iloc] = 0; - dist = (int) (strlen(fmt) - strlen(DUMP_EXT)); - if (!(strstr(fmt, DUMP_EXT) == fmt + dist)) - fmt = concat(fmt, DUMP_EXT); - if (zopen_w_input(&fmt_file, fmt, DUMP_FORMAT, FOPEN_RBIN_MODE)) - goto FOUND; - wake_up_terminal(); - fprintf(stdout, "Sorry, I can't find the format `%s'; will try `%s'.\n", - fmt, TEX_format_default); - update_terminal(); - } - /*tex Now pull out all the stops: try for the system \.{plain} file. */ - fmt = TEX_format_default; - if (!zopen_w_input(&fmt_file, fmt, DUMP_FORMAT, FOPEN_RBIN_MODE)) { - wake_up_terminal(); - fprintf(stdout, "I can't find the format file `%s'!\n", - TEX_format_default); - return NULL; - } - FOUND: - iloc = j; - return fmt; -} - -/*tex - - The global variable |name_in_progress| is used to prevent recursive use of - |scan_file_name|, since the |begin_name| and other procedures communicate via - global variables. Recursion would arise only by devious tricks like - `\.{\\input\\input f}'; such attempts at sabotage must be thwarted. - Furthermore, |name_in_progress| prevents \.{\\input} from being initiated - when a font size specification is being scanned. - - Another global variable, |job_name|, contains the file name that was first - \.{\\input} by the user. This name is extended by `\.{.log}' and `\.{.dvi}' - and `\.{.fmt}' in the names of \TeX's output files. - -*/ - -/*tex is a file name being scanned? */ - -boolean name_in_progress; - -/*tex principal file name */ - -str_number job_name; - -/*tex has the transcript file been opened? */ - -boolean log_opened_global; - -/*tex - - Initially |job_name=0|; it becomes nonzero as soon as the true name is known. - We have |job_name=0| if and only if the `\.{log}' file has not been opened, - except of course for a short time just after |job_name| has become nonzero. - -*/ - -/*tex full name of the log file */ - -unsigned char *texmf_log_name; - -/*tex - - The |open_log_file| routine is used to open the transcript file and to help - it catch up to what has previously been printed on the terminal. - -*/ - -void open_log_file(void) -{ - /*tex previous |selector| setting */ - int old_setting; - /*tex index into |buffer| */ - int k; - /*tex end of first input line */ - int l; - char *fn; - old_setting = selector; - if (job_name == 0) - job_name = getjobname(maketexstring("texput")); - fn = pack_job_name(".fls"); - recorder_change_filename(fn); - fn = pack_job_name(".log"); - while (!lua_a_open_out(&log_file, fn, 0)) { - /*tex - - Try to get a different log file name. Sometimes |open_log_file| is - called at awkward moments when \TeX\ is unable to print error - messages or even to |show_context|. The |prompt_file_name| routine - can result in a |fatal_error|, but the |error| routine will not be - invoked because |log_opened| will be false. - - The normal idea of |batch_mode| is that nothing at all should be - written on the terminal. However, in the unusual case that no log - file could be opened, we make an exception and allow an explanatory - message to be seen. - - Incidentally, the program always refers to the log file as a - `\.{transcript file}', because some systems cannot use the extension - `\.{.log}' for this file. - */ - selector = term_only; - fn = prompt_file_name("transcript file name", ".log"); - } - texmf_log_name = (unsigned char *) xstrdup(fn); - selector = log_only; - log_opened_global = true; - if (callback_defined(start_run_callback) == 0) { - /*tex Print the banner line, including current date and time. */ - log_banner(luatex_version_string); - /*tex Make sure bottom level is in memory. */ - input_stack[input_ptr] = cur_input; - tprint_nl("**"); - /*tex The last position of first line. */ - l = input_stack[0].limit_field; - if (buffer[l] == end_line_char_par) { - /*tex maybe also handle multichar endlinechar */ - decr(l); - } - for (k = 1; k <= l; k++) { - print_char(buffer[k]); - } - /*tex now the transcript file contains the first line of input */ - print_ln(); - } - /*tex should be done always */ - flush_loggable_info(); - /*tex should be done always */ - selector = old_setting + 2; -} - -/*tex - - This function is needed by synctex to make its log appear in the right spot - when |output_directory| is set. - -*/ - -char *get_full_log_name (void) -{ - if (output_directory) { - char *ret = xmalloc(strlen((char *)texmf_log_name)+2+strlen(output_directory)); - ret = strcpy(ret, output_directory); - strcat(ret, "/"); - strcat(ret, (char *)texmf_log_name); - return ret; - } else { - return xstrdup((const char*)texmf_log_name); - } -} - -/*tex Synctex uses this to get the anchored path of an input file. */ - -char *luatex_synctex_get_current_name (void) -{ - char *pwdbuf = NULL, *ret; - if (kpse_absolute_p(fullnameoffile, false)) { - return xstrdup(fullnameoffile); - } - pwdbuf = xgetcwd(); - ret = concat3(pwdbuf, DIR_SEP_STRING, fullnameoffile); - free(pwdbuf) ; - return ret; -} - -/*tex - - Let's turn now to the procedure that is used to initiate file reading when an - `\.{\\input}' command is being processed. - -*/ - -void start_input(void) -{ - str_number temp_str; - char *fn; - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - back_input(); - if (cur_cmd != left_brace_cmd) { - /*tex Set |cur_name| to desired file name. */ - scan_file_name(); - } else { - scan_file_name_toks(); - } - fn = pack_file_name(cur_name, cur_area, cur_ext); - while (1) { - /*tex Set up |cur_file| and new level of input. */ - begin_file_reading(); - if (lua_a_open_in(&cur_file, fn, 0)) { - break; - } - /*tex Remove the level that didn't work. */ - end_file_reading(); - fn = prompt_file_name("input file name", ""); - } - iname = maketexstring(fullnameoffile); - /*tex - - Now that we have |fullnameoffile|, it is time to post-adjust |cur_name| - and |cur_ext| for trailing |.tex|. - - */ - { - char *n, *p; - n = p = fullnameoffile + strlen(fullnameoffile); - while (p>fullnameoffile) { - p--; - if (IS_DIR_SEP(*p)) { - break; - } - } - if (IS_DIR_SEP(*p)) { - p++; - } - while (n>fullnameoffile) { - n--; - if (*n == '.') { - break; - } - } - if (n>p) { - int q = *n; - cur_ext = maketexstring(n); - *n = 0; - cur_name = maketexstring(p); - *n = q; - } - } - source_filename_stack[in_open] = iname; - full_source_filename_stack[in_open] = xstrdup(fullnameoffile); - /*tex We can try to conserve string pool space now. */ - temp_str = search_string(iname); - if (temp_str > 0) { - flush_str(iname); - iname = temp_str; - } - if (job_name == 0) { - job_name = getjobname(cur_name); - open_log_file(); - } - /*tex - - |open_log_file| doesn't |show_context|, so |limit| and |loc| needn't be - set to meaningful values yet. - - */ - report_start_file(filetype_tex,fullnameoffile); - incr(open_parens); - update_terminal(); - istate = new_line; - /*tex Prepare new file {\sl Sync\TeX} information. */ - if (! synctex_get_no_files()) { - /*tex Give control to the {\sl Sync\TeX} controller. */ - synctexstartinput(); - } - /*tex - - Read the first line of the new file. Here we have to remember to tell the - |lua_input_ln| routine not to start with a |get|. If the file is empty, - it is considered to contain a single blank line. - - */ - line = 1; - if (lua_input_ln(cur_file, 0, false)) { - ; - } - firm_up_the_line(); - if (end_line_char_inactive) - decr(ilimit); - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - first = ilimit + 1; - iloc = istart; -} - -/*tex - - Because the format is zipped we read and write dump files through zlib. - Earlier versions recast |*f| from |FILE *| to |gzFile|, but there is no - guarantee that these have the same size, so a static variable is needed. - -*/ - -static gzFile gz_fmtfile = NULL; - -/*tex - - As distributed, the dump files are architecture dependent; specifically, - BigEndian and LittleEndian architectures produce different files. These - routines always output BigEndian files. This still does not guarantee them to - be architecture-independent, because it is possible to make a format that - dumps a glue ratio, i.e., a floating-point number. Fortunately, none of the - standard formats do that. - -*/ - -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - -/*tex - - This macro is always invoked as a statement. It assumes a variable `temp'. - -*/ - -# define SWAP(x, y) do { temp = x; x = y; y = temp; } while (0) - -/*tex - - Make the NITEMS items pointed at by P, each of size SIZE, be the - opposite-endianness of whatever they are now. - -*/ - -static void swap_items(char *pp, int nitems, int size) -{ - char temp; - unsigned total = (unsigned) (nitems * size); - char *q = xmalloc(total); - char *p = q; - memcpy(p,pp,total); - /*tex - - Since `size' does not change, we can write a while loop for each case, - and avoid testing `size' for each time. - - */ - switch (size) { - case 16: - /*tex - - 16-byte items happen on the DEC Alpha machine when we are not doing - sharable memory dumps. - - */ - while (nitems--) { - SWAP(p[0], p[15]); - SWAP(p[1], p[14]); - SWAP(p[2], p[13]); - SWAP(p[3], p[12]); - SWAP(p[4], p[11]); - SWAP(p[5], p[10]); - SWAP(p[6], p[9]); - SWAP(p[7], p[8]); - p += size; - } - break; - - case 12: - while (nitems--) { - SWAP(p[0], p[11]); - SWAP(p[1], p[10]); - SWAP(p[2], p[9]); - SWAP(p[3], p[8]); - SWAP(p[4], p[7]); - SWAP(p[5], p[6]); - p += size; - } - break; - - case 8: - while (nitems--) { - SWAP(p[0], p[7]); - SWAP(p[1], p[6]); - SWAP(p[2], p[5]); - SWAP(p[3], p[4]); - p += size; - } - break; - - case 4: - while (nitems--) { - SWAP(p[0], p[3]); - SWAP(p[1], p[2]); - p += size; - } - break; - - case 2: - while (nitems--) { - SWAP(p[0], p[1]); - p += size; - } - break; - case 1: - /*tex Nothing to do. */ - break; - default: - FATAL1("Can't swap a %d-byte item for (un)dumping", size); - } - memcpy(pp,q,total); - xfree(q); -} -#endif - -/*tex - - That second swap is to make sure following calls don't get confused in the - case of |dump_things|. - -*/ - -void do_zdump(char *p, int item_size, int nitems, FILE * out_file) -{ - int err; - (void) out_file; - if (nitems == 0) - return; -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif - if (gzwrite(gz_fmtfile, (void *) p, (unsigned) (item_size * nitems)) != - item_size * nitems) { - fprintf(stderr, "! Could not write %d %d-byte item(s): %s.\n", nitems, item_size, gzerror(gz_fmtfile, &err)); - uexit(1); - } -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif -} - -void do_zundump(char *p, int item_size, int nitems, FILE * in_file) -{ - int err; - (void) in_file; - if (nitems == 0) - return; - if (gzread(gz_fmtfile, (void *) p, (unsigned) (item_size * nitems)) <= 0) { - fprintf(stderr, "Could not undump %d %d-byte item(s): %s.\n", nitems, item_size, gzerror(gz_fmtfile, &err)); - uexit(1); - } -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif -} - -/*tex - - Tests has shown that a level 3 compression is the most optimal tradeoff - between file size and load time. - -*/ - -#define COMPRESSION "R3" - -boolean zopen_w_input(FILE ** f, const char *fname, int format, const_string fopen_mode) -{ - int callbackid; - int res; - char *fnam; - callbackid = callback_defined(find_format_file_callback); - if (callbackid > 0) { - res = run_callback(callbackid, "S->R", fname, &fnam); - if (res && fnam && strlen(fnam) > 0) { - *f = fopen(fnam, fopen_mode); - if (*f == NULL) { - return 0; - } - } else { - return 0; - } - } else { - res = luatex_open_input(f, fname, format, fopen_mode, true); - } - if (res) { - gz_fmtfile = gzdopen(fileno(*f), "rb" COMPRESSION); - } - return res; -} - -boolean zopen_w_output(FILE ** f, const char *s, const_string fopen_mode) -{ - int res = 1; - if (luainit) { - *f = fopen(s, fopen_mode); - if (*f == NULL) { - return 0; - } - } else { - res = luatex_open_output(f, s, fopen_mode); - } - if (res) { - gz_fmtfile = gzdopen(fileno(*f), "wb" COMPRESSION); - } - return res; -} - -void zwclose(FILE * f) -{ - (void) f; - gzclose(gz_fmtfile); -} - -/*tex Create the \DVI\ or \PDF\ file. */ - -int open_outfile(FILE ** f, const char *name, const char *mode) -{ - FILE *res; - res = fopen(name, mode); - if (res != NULL) { - *f = res; - return 1; - } - return 0; -} - -/*tex The caller should set |tfm_buffer=NULL| and |tfm_size=0|. */ - -int readbinfile(FILE * f, unsigned char **tfm_buffer, int *tfm_size) -{ - void *buf; - int size; - if (fseek(f, 0, SEEK_END) == 0) { - size = (int) ftell(f); - if (size > 0) { - buf = xmalloc((unsigned) size); - if (fseek(f, 0, SEEK_SET) == 0) { - if (fread((void *) buf, (size_t) size, 1, f) == 1) { - *tfm_buffer = (unsigned char *) buf; - *tfm_size = size; - return 1; - } - } - } else { - *tfm_buffer = NULL; - *tfm_size = 0; - return 1; - } - } - /*tex Either seek failed or we have a zero-sized file. */ - return 0; -} - -/*tex - - Like |os.execute()|, the |runpopen()| function is called only when - |shellenabledp == 1|. Unlike |os.execute()| we write errors to stderr, since - we have nowhere better to use; and of course we return a file handle (or - NULL) instead of a status indicator. - -*/ - -static FILE *runpopen(char *cmd, const char *mode) -{ - FILE *f = NULL; - char *safecmd = NULL; - char *cmdname = NULL; - int allow; -#ifdef WIN32 - char *pp; - - for (pp = cmd; *pp; pp++) { - if (*pp == '\'') *pp = '"'; - } -#endif - /*tex If |restrictedshell| is zero, any command is allowed. */ - if (restrictedshell == 0) { - allow = 1; - } else { - const char *thecmd = cmd; - allow = shell_cmd_is_allowed(thecmd, &safecmd, &cmdname); - } - if (allow == 1) - f = popen(cmd, mode); - else if (allow == 2) - f = popen(safecmd, mode); - else if (allow == -1) - fprintf(stderr, "\nrunpopen quotation error in command line: %s\n", cmd); - else - fprintf(stderr, "\nrunpopen command not allowed: %s\n", cmdname); - if (safecmd) - free(safecmd); - if (cmdname) - free(cmdname); - return f; -} - -/*tex - - The code that implements |popen()| needs an array for tracking possible pipe - file pointers, because these need to be closed using |pclose()|. - -*/ - -#define NUM_PIPES 16 -static FILE *pipes[NUM_PIPES]; - -#ifdef WIN32 -FILE *Poptr; -#endif - -boolean open_in_or_pipe(FILE ** f_ptr, char *fn, int filefmt, const_string fopen_mode, boolean must_exist) -{ - string fname = NULL; - int i; - /*tex - - Opening a read pipe is straightforward, only have to skip past the pipe - symbol in the file name. filename quoting is assumed to happen elsewhere - (it does :-)) - - */ - if (shellenabledp && *fn == '|') { - /*tex The user requested a pipe. */ - *f_ptr = NULL; - fname = (string) xmalloc((unsigned) (strlen(fn) + 1)); - strcpy(fname, fn); - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = xstrdup(fname); - recorder_record_input(fname + 1); - *f_ptr = runpopen(fname + 1, "r"); - free(fname); - for (i = 0; i < NUM_PIPES; i++) { - if (pipes[i] == NULL) { - pipes[i] = *f_ptr; - break; - } - } - if (*f_ptr) - setvbuf(*f_ptr, (char *) NULL, _IONBF, 0); -#ifdef WIN32 - Poptr = *f_ptr; -#endif - return *f_ptr != NULL; - } - return luatex_open_input(f_ptr, fn, filefmt, fopen_mode, must_exist); -} - - -boolean open_out_or_pipe(FILE ** f_ptr, char *fn, const_string fopen_mode) -{ - string fname; - int i; - /*tex - - Opening a write pipe takes a little bit more work, because TeX will - perhaps have appended ".tex". To avoid user confusion as much as - possible, this extension is stripped only when the command is a bare - word. Some small string trickery is needed to make sure the correct - number of bytes is free()-d afterwards. - */ - if (shellenabledp && *fn == '|') { - /*tex The user requested a pipe. */ - fname = (string) xmalloc((unsigned) (strlen(fn) + 1)); - strcpy(fname, fn); - if (strchr(fname, ' ') == NULL && strchr(fname, '>') == NULL) { - /*tex - - \METAPOST\ and \METAFIONT\ currently do not use this code, but it - is better to be prepared. Hm, what has this todo with \LUATEX ? - - */ - if (STREQ((fname + strlen(fname) - 3), "tex")) - *(fname + strlen(fname) - 4) = 0; - *f_ptr = runpopen(fname + 1, "w"); - *(fname + strlen(fname)) = '.'; - } else { - *f_ptr = runpopen(fname + 1, "w"); - } - recorder_record_output(fname + 1); - free(fname); - for (i = 0; i < NUM_PIPES; i++) { - if (pipes[i] == NULL) { - pipes[i] = *f_ptr; - break; - } - } - if (*f_ptr) - setvbuf(*f_ptr, (char *) NULL, _IONBF, 0); - return *f_ptr != NULL; - } - return luatex_open_output(f_ptr, fn, fopen_mode); -} - - -void close_file_or_pipe(FILE * f) -{ - int i; - if (shellenabledp) { - for (i = 0; i <= 15; i++) { - /*tex If this file was a pipe, |pclose()| it and return. */ - if (pipes[i] == f) { - if (f) { - pclose(f); -#ifdef WIN32 - Poptr = NULL; -#endif - } - pipes[i] = NULL; - return; - } - } - } - close_file(f); -} |